1. Introduction and Aims

We have quality-controlled the 10X data and the SS2 data and now are left with the following objects:

10X 5K data - pb_sex_filtered

10X 30K data - pb_30k_sex_filtered

SS2 mutant data - ss2_mutants_final

2. Read in the data

Load/Install the Required Packages

[1] "patchwork is loaded correctly"
[1] "viridis is loaded correctly"
[1] "Seurat is loaded correctly"
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:patchwork’:

    align_plots
[1] "cowplot is loaded correctly"
Loading required package: gridExtra
[1] "gridExtra is loaded correctly"
Loading required package: grid
[1] "grid is loaded correctly"
Loading required package: Hmisc
Loading required package: lattice
Loading required package: survival
Loading required package: Formula
Loading required package: ggplot2

Attaching package: ‘Hmisc’

The following object is masked from ‘package:Seurat’:

    Key

The following objects are masked from ‘package:base’:

    format.pval, units
[1] "Hmisc is loaded correctly"
Loading required package: reshape2
[1] "reshape2 is loaded correctly"
Loading required package: dplyr

Attaching package: ‘dplyr’

The following objects are masked from ‘package:Hmisc’:

    src, summarize

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
[1] "dplyr is loaded correctly"
Loading required package: Nebulosa
[1] "Nebulosa is loaded correctly"
Loading required package: monocle3
Loading required package: Biobase
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ, clusterExport, clusterMap, parApply, parCapply,
    parLapply, parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:dplyr’:

    combine, intersect, setdiff, union

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated, eval, evalq,
    Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget, order, paste, pmax,
    pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames, sapply, setdiff, sort, table, tapply,
    union, unique, unsplit, which, which.max, which.min

Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
    'citation("Biobase")', and for packages 'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:Hmisc’:

    contents

Loading required package: SingleCellExperiment
Loading required package: SummarizedExperiment
Loading required package: GenomicRanges
Loading required package: stats4
Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:dplyr’:

    first, rename

The following object is masked from ‘package:base’:

    expand.grid

Loading required package: IRanges

Attaching package: ‘IRanges’

The following objects are masked from ‘package:dplyr’:

    collapse, desc, slice

Loading required package: GenomeInfoDb
Loading required package: DelayedArray
Loading required package: matrixStats

Attaching package: ‘matrixStats’

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians

The following object is masked from ‘package:dplyr’:

    count


Attaching package: ‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following objects are masked from ‘package:base’:

    aperm, apply, rowsum


Attaching package: ‘SummarizedExperiment’

The following object is masked from ‘package:Seurat’:

    Assays


Attaching package: ‘monocle3’

The following objects are masked from ‘package:Biobase’:

    exprs, fData, fData<-, pData, pData<-
[1] "monocle3 is loaded correctly"

Read in the Data

screen hits

## EDIT - change this to the excel table once we have it finalized for the screen
screen_hits <- c("PBANKA-0516300",
"PBANKA-1217700",
"PBANKA-0409100",
"PBANKA-1034300",
"PBANKA-1437500",
"PBANKA-0827500",
"PBANKA-0824300",
"PBANKA-1426900",
"PBANKA-0105300",
"PBANKA-0921100",
"PBANKA-1002400",
"PBANKA-0829400",
"PBANKA-1347200",
"PBANKA-0828000",
"PBANKA-0902300",
"PBANKA-1418100",
"PBANKA-1435200",
"PBANKA-1454800",
"PBANKA-0712300",
"PBANKA-0410500",
"PBANKA-1144800",
"PBANKA-1231600",
"PBANKA-0503200",
"PBANKA-0308900",
"PBANKA-1214700",
"PBANKA-0709900",
"PBANKA-0311900",
"PBANKA-0716500",
"PBANKA-1447900",
"PBANKA-0102200",
"PBANKA-0713500",
"PBANKA-0102400",
"PBANKA-1302700",
"PBANKA-1235900",
"PBANKA-0401100",
"PBANKA-0413400",
"PBANKA-1126900",
"PBANKA-1425900",
"PBANKA-0418300",
"PBANKA-1464600",
"PBANKA-0806000")

Read in gene annotations

gene_annotations <- read.table("../data/Reference/GenesByTaxon_Summary.csv", header = TRUE, sep = ",", stringsAsFactors = TRUE)
dim(gene_annotations)

## convert _ to -
gene_annotations$Gene.ID <- gsub("_", "-", gene_annotations$Gene.ID)

load in datasets

paste("10x dataset")
[1] "10x dataset"
pb_sex_filtered
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("Smart-seq2 dataset")
[1] "Smart-seq2 dataset"
ss2_mutants_final
An object of class Seurat 
5245 features across 2717 samples within 1 assay 
Active assay: RNA (5245 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("The composition of the Smart-seq2 dataset is:")
[1] "The composition of the Smart-seq2 dataset is:"
table(ss2_mutants_final@meta.data$genotype)

Mutant     WT 
  2028    689 

3. Merging the Smart-seq2 and 10X Data

Prepare data

tenx_5k_counts_to_integrate
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 0 variable features)

We need to make sure the mutant data is compatible with the 10X data. the 10X data has fewer genes represented so we need to find the intersect of the two before integration.

GCSKO_mutants
An object of class Seurat 
5018 features across 2717 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## double check that this is the same number of genes
## subset counts so that only genes represented in the other two objects are there:
length(intersect(rownames(tenx_5k_counts), rownames(mutant_counts_for_integration)))
[1] 5018

IMPORTANT - this next step is different to GCSKO_merge as it subsets the smart-seq2 data into wild-type only.

## subset wt on ss2 data:
ss2_wt_cells <- rownames(GCSKO_mutants@meta.data[GCSKO_mutants@meta.data$genotype == "WT", ])
GCSKO_mutants_wtonly <- subset(GCSKO_mutants, cells = ss2_wt_cells)

create list and normalise:

## make list
tenx.justwt.list <- list(tenx_5k_counts_to_integrate, GCSKO_mutants_wtonly)

## prepare data
for (i in 1:length(tenx.justwt.list)) {
    tenx.justwt.list[[i]] <- NormalizeData(tenx.justwt.list[[i]], verbose = FALSE)
    tenx.justwt.list[[i]] <- FindVariableFeatures(tenx.justwt.list[[i]], selection.method = "vst", 
        nfeatures = 2000, verbose = FALSE)
    all.genes <- rownames(tenx.justwt.list[[i]])
    tenx.justwt.list[[i]] <- ScaleData(tenx.justwt.list[[i]], features = all.genes)
}

Integrate objects

## Find anchors
tenx.justwt.anchors <- FindIntegrationAnchors(object.list = tenx.justwt.list, dims = 1:21, verbose = FALSE)

## Integrate data
tenx.justwt.integrated <- IntegrateData(anchorset = tenx.justwt.anchors, dims = 1:21, verbose = FALSE, features.to.integrate = genes_in_tenx_dataset)

4. Dimensionality reduction

PCA

Optimised UMAP

After optimisation, the following UMAP can be calculated:

## Run optimised UMAP
tenx.justwt.integrated <- RunUMAP(tenx.justwt.integrated, reduction = "pca", dims = 1:10, n.neighbors = 50, seed.use = 1234, min.dist = 0.4, repulsion.strength = 0.03, local.connectivity = 150)

Make final plots:


## split seurat object up
ob.list <- SplitObject(tenx.justwt.integrated, split.by = "experiment")

## make plots for each object
plot.list <- lapply(X = ob.list, FUN = function(x) {
    DimPlot(x, dims = c(1,2), pt.size = 1) + theme(legend.position="bottom")
})

composition_umap_10x <- plot.list$`tenx_5k` + 
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(45, "#999999"))) +
  labs(title = paste("10x (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap_ss2 <- plot.list$mutants +
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(46, "#999999"))) +
  labs(title = paste("Smart-seq2 (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap <- composition_umap_10x + composition_umap_ss2 

composition_umap

save

ggsave("../images_to_export/composition_umap.png", plot = composition_umap, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)
## make plots
## hoo dataset correlation
UMAP_hoo <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman.", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("Hoo Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(12))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## ap2g timecourse in this paper correlation
UMAP_kasia <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman._Kasia", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("AP2G Timecourse Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(10))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## combine
umap_bulk <- wrap_plots(UMAP_hoo, UMAP_kasia, ncol = 2)

## print
umap_bulk

5. Clustering

Generate clusters

## generate new clusters at low resolution
tenx.justwt.integrated <- FindNeighbors(tenx.justwt.integrated, dims = 1:19, reduction = "pca")
tenx.justwt.integrated <- FindClusters(tenx.justwt.integrated, resolution = 2, random.seed = 42, algorithm = 2)

visualise clusters

DimPlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE, repel = FALSE, label = TRUE)

Make individual plots highlighting where cells in each cluster fall

[1] 24

plot

## this function writes the next bit of code for you
## put it into the console and paste the response
#ploty <- c()
#for(i in seq_along(levels(tenx.justwt.integrated@meta.data$seurat_clusters))){
#  ploty <- paste0(ploty, "list_UMAPs_by_cluster[[", i, "]]", " + ")
#}

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Find Markers

visualise markers

## get the top 10 for each cluster
top10 <- pb.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)

## scale data is missing - but original dfs have scale.data
# df_scaled <- as.matrix(transform(merge(as.data.frame(tenx.justwt.list[[1]]@assays$RNA@scale.data), as.data.frame(tenx.justwt.list[[2]]@assays$RNA@scale.data), by = 0, all=FALSE), row.names=Row.names, Row.names=NULL))
# tenx.justwt.integrated@assays$RNA@scale.data <- df_scaled

## scale data in RNA slot
all.genes <- rownames(tenx.justwt.integrated)
tenx.justwt.integrated <- ScaleData(tenx.justwt.integrated, vars.to.regress = 'experiment', features = all.genes)

## heatmap
DoHeatmap(tenx.justwt.integrated, features = top10$gene) + NoLegend()

6. Define Cluster Identities

Downsampling

# ## check number of cells in each cluster
# df_clusters <- as.data.frame(table(tenx.justwt.integrated@meta.data$integrated_snn_res.2))
# plot(df_clusters)
# 
# ## downsample using appropriate metrics
# tenx.justwt.integrated.downsampled <- subset(tenx.justwt.integrated, downsample = 100)
#   
# ## inspect plot
# FeaturePlot(tenx.justwt.integrated.downsampled, features = "PBANKA-1437500", coord.fixed = TRUE, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
#   theme_void() + 
#   labs(title = paste("AP2G (Commitment)")) + 
#   theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
#   scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

Marker Genes

useful tools for all plots

## define male and female symbol
female_symbol <- intToUtf8(9792)
male_symbol <- intToUtf8(9794)

## define colour pal
marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

Expression - cutoffs - purple


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1319500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ccp2)~(Female))) + 
                          theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=6.0), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, 
                                    features = "PBANKA-0416100", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') +
                        coord_fixed() + 
                        theme_void() + 
                        labs(title = expression(italic(mg1)~(Male))) + 
                        theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                        scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1437500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ap2g)~(Commitment))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0831000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp1)~(Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1102200", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp8)~(Asexual))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1102200 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1101300", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(SBP1)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0722600", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(fam-b2)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0722600 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_ORC1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0602000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(orc1)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0602000 in the default search locations, found in RNA assay insteadCoordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_CDPK5 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1351500", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(cdpk5)~(Line~Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MCM4 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1415600", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(mcm4)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
# + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

Mutant Genes

Expression - with cutoffs

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD4 
# PBANKA-0716500        GCSKO-19  MD5 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_fd3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1418100", 
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                        theme_void() + 
                        labs(title = expression(italic(fd3))) + 
                        theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-1418100 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                        ## add sex symbols
                        #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                        #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md4 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap", 
                                  features = "PBANKA-0102400", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05",
                                  max.cutoff = "q95", 
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                      theme_void() + 
                      labs(title = expression(italic(md4))) + 
                      theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                      ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                      #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md5 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0716500", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md5))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd4 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-1435200", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd4))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = "")) 
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd2 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-0902300", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       # + annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md3 <- FeaturePlot(tenx.justwt.integrated, 
                                   dims = c(1,2), 
                                   reduction = "umap", 
                                   features = "PBANKA-0413400", 
                                   coord.fixed = TRUE, 
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95",
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md3))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0413400 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                      #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_gd1 <- FeaturePlot(tenx.justwt.integrated, 
                                  dims = c(1,2), 
                                  reduction = "umap",
                                  features = "PBANKA-0828000", 
                                  coord.fixed = TRUE, 
                                  min.cutoff = "q05", 
                                  max.cutoff = "q95",
                                  pt.size = 0.5, 
                                  order = TRUE, 
                                  slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(gd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Could not find PBANKA-0828000 in the default search locations, found in RNA assay insteadScale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1302700",
                                    coord.fixed = TRUE,
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_md2 <- FeaturePlot(tenx.justwt.integrated,
                                   dims = c(1,2), 
                                   reduction = "umap",
                                   features = "PBANKA-1447900",
                                   coord.fixed = TRUE,
                                   min.cutoff = "q05", 
                                   max.cutoff = "q95", 
                                   pt.size = 0.5, 
                                   order = TRUE, 
                                   slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(md2))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_fd1 <- FeaturePlot(tenx.justwt.integrated, 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    features = "PBANKA-1454800", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05",
                                    max.cutoff = "q95", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') + 
                       theme_void() + 
                       labs(title = expression(italic(fd1))) + 
                       theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=7), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
                       ## add sex symbols
                       #annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
                       #annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))
# scale_color_continuous_sequential(palette = "Purples 2")
# scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_gd1 , marker_gene_plot_md1 , marker_gene_plot_md2 , marker_gene_plot_md3 , marker_gene_plot_md4 , marker_gene_plot_md5 , marker_gene_plot_fd1 , marker_gene_plot_fd2 , marker_gene_plot_fd3 , marker_gene_plot_fd4, ncol = 4)
           
## print
mutant_expression_composite

save

ggsave("../images_to_export/ALL_CELLS_wt_gene_expression.png", plot = mutant_expression_composite, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

7. Pseudotime on all cells

Pseudotime calculation

save

ggsave("../images_to_export/UMAP_pt_wt.png", plot = umap_pt, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)

gganimnate GIF of pseuodtime

#install.packages("gganimate")
library(gganimate)
#install.packages("gifski")
#install.packages("av")
#library(gifski)
#library(av)

## make dataframe for plotting
## extract data for GGplot version of this
df_animation <- as.data.frame(monocle.object.all@int_colData@listData$reducedDims@listData[["UMAP"]])
## add pt to this data frame:
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))
df_animation <- merge(df_animation, pt_values, by="row.names") 
rownames(df_animation) <- df_animation$Row.names
colnames(df_animation)[4] <- "pt"

## make the static plot
p <- ggplot(df_animation, aes(x = UMAP_1, y = UMAP_2, colour = pt)) +
  geom_point() +
  scale_colour_viridis_c(option = "plasma") +
  coord_fixed() +
  theme_void() +
  theme(legend.position = "none")
## view plot
plot(p)

## make animated plot
## make a category for animation
#df_animation$group <- cut(df_animation$pt, 15)

anim <- p +
  transition_time(pt) +
  shadow_mark()

animate(anim, height = 3, width = 3, units = "in", res = 150, bg = 'transparent')

## to change the resolution - https://stackoverflow.com/questions/49058567/define-size-for-gif-created-by-gganimate-change-dimension-resolution 

Save animation

anim_save("animated_UMAP_transparent_bg_wt.gif", path = "../images_to_export/")
## extract pt values
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))

tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, pt_values, "old_pt_values")

Define cell identities with branches

Define identities of cells

male

monocle.object_male <- choose_graph_segments(monocle.object.all)

female

monocle.object_female <- choose_graph_segments(monocle.object.all)

bipotential

monocle.object_bipot <- choose_graph_segments(monocle.object.all)

asexual (pre-branch)

monocle.object_asex_pre <- choose_graph_segments(monocle.object.all)

asexual fate

monocle.object_asex_fate <- choose_graph_segments(monocle.object.all)

check

df_freq <- data.frame(table(c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex_pre), colnames(monocle.object_asex_fate))))
paste("number of cells in seurat object is", length(colnames(monocle.object.all)), ". The number of cells selected here with an identitity is", dim(df_freq)[1])
df_freq <- df_freq[df_freq$Freq > 1, ]
df_freq

Inspect where these missing cells are:

# '%ni%' <- Negate('%in%')
# 
# not_assigned_cells <- colnames(monocle.object.all)[colnames(monocle.object.all) %ni% c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex), colnames(monocle.object_asex_fate))]
# 
# DimPlot(seurat.object, repel = TRUE, label.size = 5, pt.size = 0.5, cells.highlight = not_assigned_cells, dims = c(2,1), reduction = "DIM_UMAP") +
#   coord_fixed() + 
#   scale_color_manual(values=c("#000000", "#f54e1e"))
## create annotation dataframe from these results:
df_monocle_sexes <- rbind(data.frame("cell_name" = colnames(monocle.object_male), "sex" = rep("Male", length(colnames(monocle.object_male)))),
                          data.frame("cell_name" = colnames(monocle.object_female), "sex" = rep("Female", length(colnames(monocle.object_female)))),
                          data.frame("cell_name" = colnames(monocle.object_bipot), "sex" = rep("Bipotential", length(colnames(monocle.object_bipot)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_pre), "sex" = rep("Asexual_Early", length(colnames(monocle.object_asex_pre)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_fate), "sex" = rep("Asexual_Late", length(colnames(monocle.object_asex_fate))))
                          #data.frame("cell_name" = not_assigned_cells, "sex" = rep("Unassigned", length(not_assigned_cells)))
                          )

dim(df_monocle_sexes)

## order like the metadata
df_monocle_sexes <- df_monocle_sexes[match(rownames(monocle.object.all@colData), df_monocle_sexes$cell_name), ]

## add this back into the monocle object
monocle.object.all@colData$Sexes_monocle <- df_monocle_sexes$sex

## add this to the seurat object
rownames(df_monocle_sexes) <- df_monocle_sexes$cell_name
df_monocle_sexes_to_add_to_seurat <- df_monocle_sexes[,c("sex"), drop = FALSE]
tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, df_monocle_sexes_to_add_to_seurat, col.name = "monocle_sex")

pt vs. real time

gg <- ggplot(df_plotting, aes(as.factor(Prediction.Spearman.), fill = monocle_sex)) + geom_bar(stat = "count", position="fill")

gg

8. Plots

make composite pseudotime/ID figure

save

#ggsave("../images_to_export/umap_id_pt.png", plot = umap_id_pt, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

cluster plot

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## make a new column for plotting
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## change the levels
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(A_1="9", 
                                      A_2="4", 
                                      A_3="15", 
                                      A_4 = "8", 
                                      A_5 = "1",
                                      A_6=  "14", 
                                      A_7 = "2", 
                                      A_8 = "10",
                                      A_9 = "3",
                                      A_10 = "0",
                                      A_11 = "6",
                                      A_12 = "5",
                                      A_13 = "7",
                                      A_14 = "12",
                                      A_15 = "18",
                                      A_16 = "20",
                                      A_17 = "23",
                                      P = "11",
                                      M_1 = "16",
                                      M_2 = "13",
                                      F_1 = "21",
                                      F_2 = "22",
                                      F_3 = "19",
                                      F_3 = "17"
                                      )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## make colour pallete
#pal_plot <- c(asex_ramp(170)[1,11,21,31,], bipot_ramp(3)[2], male_ramp(5)[3:4], female_ramp(5)[2:5])
pal_plot <- c(df_annotation$colour, '#49C16DFF')

## plot
umap_with_clusters <- DimPlot(tenx.justwt.integrated,
        group.by = "seurat_clusters_dot_plotting",
        dims = c(1,2), 
        reduction = "umap", 
        pt.size = 1,
        label.box = TRUE,
        label.size = 8,
        label.color = c(rep(c("#000000"), 12), rep(c("#ffffff"), 5), rep(c("#000000"), 2),"#ffffff", "#000000", "#ffffff", "#ffffff"),
        order = TRUE, 
        repel = TRUE, 
        label = TRUE,
        cols = pal_plot) +
  scale_color_manual(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3"), values = pal_plot) +
  theme_void() +
                     coord_fixed()
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
umap_with_clusters

save

ggsave("../images_to_export/umap_with_clusters.png", plot = umap_with_clusters, device = "png", path = NULL, scale = 1, width = 21, height = 29.5, units = "cm", dpi = 300, limitsize = TRUE)

ggsave("../images_to_export/WT_cell_type_proportions.png", plot = plot_prop, device = "png", path = NULL, scale = 1, width = 30, height = 9, units = "cm", dpi = 300, limitsize = TRUE)

dotplot

A dotplot allows us to look at the expression of multiple genes in a clearer way than succesive UMAP plots

### Data set-up

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0102400         GCSKO-2  MD5 

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

# PBANKA-1437500 - AP2G - commitment
# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)

marker_genes_list <- c("PBANKA-1437500", "PBANKA-1319500", "PBANKA-0416100", "PBANKA-0831000", "PBANKA-1102200")
mutant_genes_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0413400", "PBANKA-0716500", "PBANKA-0102400",  "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## copy the clusters so you don't permanently edit the master
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)

## reorder the levels
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## rename clusters so that they are intuitive
# this trick is from here: http://www.cookbook-r.com/Manipulating_data/Renaming_levels_of_a_factor/
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(Asexual_1="9", 
                                                                              Asexual_2="4", 
                                                                              Asexual_3="15", 
                                                                              Asexual_4 = "8", 
                                                                              Asexual_5 = "1",
                                                                              Asexual_6=  "14", 
                                                                              Asexual_7 = "2", 
                                                                              Asexual_8 = "10",
                                                                              Asexual_9 = "3",
                                                                              Asexual_10 = "0",
                                                                              Asexual_11 = "6",
                                                                              Asexual_12 = "5",
                                                                              Asexual_13 = "7",
                                                                              Asexual_14 = "12",
                                                                              Asexual_15 = "18",
                                                                              Asexual_16 = "20",
                                                                              Asexual_17 = "23",
                                                                              Bipotential = "11",
                                                                              Male_1 = "16",
                                                                              Male_2 = "13",
                                                                              Female_1 = "21",
                                                                              Female_2 = "22",
                                                                              Female_3 = "19",
                                                                              Female_3 = "17"
                                                                              )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## plot annotation 
## this really helped: https://www.biostars.org/p/396810/
h2 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h2 <- h2 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)
 
 h1 <- ggplot(df_annotation)+
  geom_point(mapping = aes(x = Group.1, y = 1),
            col = df_annotation$colour,
            size = 5)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h1 <- h1 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)

 ## add predicted time point
 ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman."], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h3 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")

  h3 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis(option = 'cividis')
 legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")
 
 ## add kasia data
  ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman._Kasia"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h4 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))+
     facet_grid(.~colour, scales = "free_x")
     legend <- plot_grid(get_legend(h4), ncol = 1)
    legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

 h4 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis()
 legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

### Plot
dot_plot_markers <- DotPlot(tenx.justwt.integrated, 
                            features = c(marker_genes_list, rev(mutant_genes_list)), 
                            group.by = "seurat_clusters_dot_plotting", 
                            dot.min = 0.00001,
                            assay = 'RNA') +
  theme_classic() +
  coord_fixed() +
  coord_flip() +
  # change appearance and remove axis elements, and make room for arrows
  theme(axis.text.x = element_text(size=16, angle = 45, hjust=1,vjust=1, family = "Arial"), 
        axis.text.y = element_text(size=16, face="italic"), 
        text=element_text(size=16, family="Arial", colour="black"), 
        legend.position = "bottom", 
        legend.direction = "horizontal", 
        legend.box = "vertical", 
        plot.title = element_blank(), 
        plot.margin = unit(c(1,3,1,3), "lines"), 
        axis.line = element_blank(),
        panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
  #change the colours
  #scale_colour_viridis(option = "inferno", guide = "colourbar", na.value="white", begin = 0, end = 1, direction = 1) +
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## change x axis label
  # labs(x = "Marker Genes", y = "Cluster", title = "Expression of Marker Genes by Cluster") 
  labs(x = "", y = "", title = "") +
  ## add arrows
  #annotate("segment", x = 5.5, xend = 5.5, y = 21.5, yend = 25, colour = "green", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 16.5, yend = 21.5, colour = "red", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 0, yend = 15.5, colour = "grey", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  ## annotate asex
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate bipotential
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate sexes
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters, male_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## change label on bottom of plot so we can indicate markers
  scale_x_discrete(labels = rev(c("gd1", "md1", "md2", "md3", "md4", "md5", "fd1", "fd2", "fd3", "fd4", "msp8", "msp1", "mg1", "ccp2", "ap2g"))) +
  ## change label on bottom of plot so we can indicate markers
  scale_y_discrete(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3")) +
  ## change name of legends
  guides(col=guide_colorbar(title = 'Scaled Average Expression'),
         size=guide_legend("% of cells expressing"))

## view
#print(dot_plot_markers)

plot <- plot_grid(h4, h3, h1, dot_plot_markers, align = "v", ncol = 1, axis = "tb", rel_heights = c(0.5, 0.5, 0.5, 18)) 

dot_plot <- plot_grid(plot, legend_h3, legend_h4, nrow = 1, rel_widths = c(10, 1.5, 1.5))

dot_plot

save

ggsave("../images_to_export/dot_plot_all.png", plot = dot_plot, device = "png", path = NULL, scale = 1, width = 29.7, height = 21, units = "cm", dpi = 300, limitsize = TRUE)

9. Subset sexual cells

Make a subsetted Seurat object of sexual cells.

Include the pre-branch too as well as any weird clusters that may have clustered out.

it’s been a while since we looked at the clusters so let’s check them out again:

## Plot
DimPlot(tenx.justwt.integrated, label = TRUE, repel = FALSE, pt.size = 0.05, group.by = "seurat_clusters", dims = c(1,2), reduction = "umap") + coord_fixed()

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Define cells and subset

asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## define cells
cell_names_subset_monocle_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$monocle_sex %in% c("Asexual_Early", "Bipotential", "Male", "Female"), ])

## 3, 0, 6, 5 are early clusters of asexuals before the branch
cell_names_subset_cluster_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$seurat_clusters %in% c(male_clusters, female_clusters, bipotential_clusters, 3, 0, 6, 5), ])

cell_names_subset_intersect <- intersect(cell_names_subset_monocle_ids, cell_names_subset_cluster_ids)

## subset cells into new object
tenx.justwt.integrated.sex <- subset(tenx.justwt.integrated, cells = cell_names_subset_intersect)

inspect/check

## inspect object
tenx.justwt.integrated.sex

## look at original UMAP
DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, split.by = "experiment", dims = c(1,2), reduction = "umap") + coord_fixed()

Remove contaminant asexual cells

we want to remove:

## look at original UMAP
plot_sexual_subsetting <- DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  geom_vline(aes(xintercept = -1, alpha = 5))

plot_sexual_subsetting
## extract cell embeddings
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated.sex@reductions[["umap"]]@cell.embeddings)

## subset anything lower than -0.8 in UMAP 2 and -0.1 in UMAP 1
remove_cells <- row.names(df_sex_cell_embeddings[which(df_sex_cell_embeddings$UMAP_1 < -1), ])

## plot these cells
DimPlot(tenx.justwt.integrated.sex, label = FALSE, repel = TRUE, pt.size = 0.1, cells.highlight = remove_cells, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  scale_color_manual(values=c("#000000", "#f54e1e")) + 
  theme_void() + 
  labs(title = paste("cells highlighted will be removed")) + 
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none")

Final Subset

tenx.justwt.integrated.sex
An object of class Seurat 
10116 features across 2817 samples within 2 assays 
Active assay: RNA (5098 features, 0 variable features)
 1 other assay present: integrated
 2 dimensional reductions calculated: pca, umap

copy old clusters over

## copy old clusters
tenx.justwt.integrated.sex <- AddMetaData(tenx.justwt.integrated.sex, tenx.justwt.integrated.sex@meta.data$seurat_clusters, col.name = "post_integration_clusters")

10. Sex assignment of mutants

A. Seurat Method

## find transfer anchors
DefaultAssay(tenx.justwt.integrated) <- "integrated"
merge.anchors <- FindTransferAnchors(reference = tenx.justwt.integrated, query = GCSKO_mutants, 
    dims = 1:30)
Performing PCA on the provided reference using 2000 features as input.
Projecting PCA
Finding neighborhoods
Finding anchors
    Found 920 anchors
Filtering anchors
    Retained 610 anchors
## transfer data between ref and query
predictions <- TransferData(anchorset = merge.anchors, refdata = tenx.justwt.integrated$seurat_clusters_dot_plotting, 
    dims = 1:30)
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Predicting cell labels
## add meta data to object
GCSKO_mutants <- AddMetaData(GCSKO_mutants, metadata = predictions)

## new object from this
mutant_seurat <- GCSKO_mutants

## look at breakdown of mutant by designation
df <- as.data.frame(mutant_seurat@meta.data)
table(df$predicted.id, df$identity_name_updated)
            
             fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_1    2  43   5   7  10   4   4   6   5  42        37
  Asexual_10   6  29   5   4   9   3   9  10   1  27        42
  Asexual_12   0   1   0   0   1   1   1   0   0   0         0
  Asexual_13   2   4  10   1  35  10   4  32   5   0        15
  Asexual_14   1   3  17   3  40  25   8  15   8   4        40
  Asexual_15  19   6  19   2  24  10   4  25   6   2        25
  Asexual_16  27  13  30   4  33  49  13  75   8  14        63
  Asexual_17  10  23  15   4  13  25  13  38  12  19        48
  Female_1     2  51   5   0   6  23  64   2   1   4        37
  Female_3    19  11  14  23   0 105 141  86  14  21       160
  Male_1       0   1   0   0  48   0   0   2   9   1         2
  Male_2      65  55  14  45  14   0   0  45   8 112       220
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- df[df$genetic_background =="PBANKA_820", ]
table(df_820$predicted.id, df_820$fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      69       1
  Asexual_Late   33     459      16
  Female          2     342     240
  Male          182      49       0

inspect gd1

df[which(df$predicted.id == "Female_1" & df$identity_name_updated == "gd1"), ][, 118:146]

Calculate sex ratios

## use designations above for sexes
male_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Male", ])
female_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Female", ])
ss2_mutants_final_male <- subset(mutant_seurat, cells = male_cells)
ss2_mutants_final_female <- subset(mutant_seurat, cells = female_cells)

## inspect
ss2_mutants_final_male
An object of class Seurat 
5018 features across 636 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
ss2_mutants_final_female
An object of class Seurat 
5018 features across 788 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## calculate sex ratios
##subset out H, sorted cells:
df_male <- ss2_mutants_final_male@meta.data[ss2_mutants_final_male@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_male)
[1] 454 124
df_female <- ss2_mutants_final_female@meta.data[ss2_mutants_final_female@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_female)
[1] 546 124
## make dataframe
df_sex_ratio <- merge(
  as.data.frame(table(df_male$sub_name_updated)), 
  as.data.frame(table(df_female$sub_name_updated)), 
  by = "Var1", all=TRUE)

# or use identity_updated

## add names
names(df_sex_ratio) <- c("genotype", "male", "female")

## change the NAs to 0
df_sex_ratio[is.na(df_sex_ratio)] <- 0

## collapse 820 wild-types together
combined_m <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$male + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$male
combined_f <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$female + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$female
df_sex_ratio <- rbind(df_sex_ratio, c("WT-820-combined", combined_m, combined_f))
invalid factor level, NA generated
# remove old rows
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-820_3_5" | df_sex_ratio$genotype == "WT-820"), ]
# need to make numeric again
df_sex_ratio$male <- as.numeric(df_sex_ratio$male)
df_sex_ratio$female <- as.numeric(df_sex_ratio$female)
df_sex_ratio$genotype <- as.character(df_sex_ratio$genotype)
# add name for WT combined
df_sex_ratio$genotype[17] <- "WT-820-combined"

## calculate sex ratio
df_sex_ratio$sex_ratio <- (df_sex_ratio$male + 0.1)/(df_sex_ratio$female + 0.1)

## log sex ratio
df_sex_ratio$sex_ratio_log <- log10(df_sex_ratio$sex_ratio)

##view
df_sex_ratio
## remove WT-2 because it is really inappropriate to have a sex ratio for this:
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-md5"),]

plot

B. SCMAP Method

Build the index

### Making an ortholog reference index

## load in mca data
#counts <- read.csv("../scmap/allpb10x_counts.csv", row.names = 1)
#pheno <- read.csv("../scmap/allpb10x_pheno.csv")
#ggplot(pheno, aes(x=PC2_3d, y = PC3_3d,colour=absclust3)) + geom_point()

## load required libraries
library(scmap) #https://bioconductor.org/packages/release/bioc/html/scmap.html 
library(SingleCellExperiment) #

#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene

## extract data from Seurat
#cells_tenx <- rownames(tenx.justwt.integrated@meta.data[which(tenx.justwt.integrated@meta.data$experiment == "tenx_5k"), ])
#tenx.justwt.integrated.10k <- subset(tenx.justwt.integrated, cells = cells_tenx)
counts = as.matrix(GetAssayData(tenx.justwt.integrated, slot = "counts", assay = "RNA"))
pheno = as.data.frame(tenx.justwt.integrated@meta.data)

## add UMAP coordinates
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings)
pheno <- cbind(pheno, df_sex_cell_embeddings)

## Set up object
sce <- SingleCellExperiment(list(counts=counts),
    colData=DataFrame(label=pheno),
    rowData=DataFrame(feature_symbol=rownames(counts)))
sce
class: SingleCellExperiment 
dim: 5098 6880 
metadata(0):
assays(1): counts
rownames(5098): PBANKA-0000101 PBANKA-0000301 ... PBANKA-MIT0360 PBANKA-MIT0370
rowData names(1): feature_symbol
colnames(6880): AAACCTGGTAAGGGCT AAACCTGGTGCACTTA ... SC25027_8_95 SC25027_8_96
colData names(127): label.orig.ident label.nCount_RNA ... label.UMAP_1 label.UMAP_2
reducedDimNames(0):
altExpNames(0):
## manual logging
#counts_1 <- assay(sce, "counts")
#libsizes <- colSums(counts_1)
#size.factors <- libsizes/mean(libsizes)
#logcounts(sce) <- log2(t(t(counts_1)/size.factors) + 1)
#counts(sce) <- as.matrix(counts(sce))
#logcounts(sce) <- as.matrix(logcounts(sce))
logcounts(sce) <- as.matrix(GetAssayData(tenx.justwt.integrated, slot = "data", assay = "RNA"))

## remove features with duplicated names
sce <- sce[!duplicated(rownames(sce)), ]

## build scmap-cell reference index, save this rds
sce <- selectFeatures(sce, suppress_plot = FALSE, n_features = 2000)

table(rowData(sce)$scmap_features)

FALSE  TRUE 
 3098  2000 
set.seed(1)
sce <- indexCell(sce, M = 50, k = 80)
names(metadata(sce)$scmap_cell_index)
[1] "subcentroids" "subclusters" 
length(metadata(sce)$scmap_cell_index$subcentroids)
[1] 50
dim(metadata(sce)$scmap_cell_index$subcentroids[[1]])
[1] 40 80
metadata(sce)$scmap_cell_index$subcentroids[[1]][,1:5]
                        1           2           3           4          5
PBANKA-0100200 0.14630862 0.526027391 0.043704597 0.084187544 0.27749519
PBANKA-0100700 0.09460507 0.073257106 0.313286733 0.370676472 0.27852452
PBANKA-0100900 0.09923532 0.087566303 0.059203198 0.094759828 0.06865377
PBANKA-0101000 0.04763362 0.033790484 0.035038280 0.029494053 0.09082912
PBANKA-0101200 0.05167727 0.100910226 0.041157644 0.087829422 0.04947390
PBANKA-0101300 0.03427392 0.000000000 0.006482623 0.017440407 0.04685456
PBANKA-0101400 0.12483604 0.023321169 0.056473567 0.214402432 0.30191506
PBANKA-0101500 0.03194160 0.050889592 0.037542520 0.040676819 0.02895481
PBANKA-0101600 0.03798147 0.007504403 0.028087301 0.055265292 0.02882148
PBANKA-0101800 0.28129376 0.098383830 0.133405404 0.110619710 0.08911439
PBANKA-0101900 0.04066573 0.007504403 0.033564638 0.036681755 0.18011835
PBANKA-0102000 0.07611798 0.066861770 0.012354195 0.077811108 0.09136082
PBANKA-0102200 0.06226485 0.251753986 0.605044037 0.076494250 0.11263897
PBANKA-0102800 0.06418848 0.030164171 0.042579458 0.058224917 0.09315054
PBANKA-0103100 0.11743208 0.010838894 0.026223349 0.027978543 0.07163404
PBANKA-0103800 0.04052086 0.092749297 0.037663604 0.051866920 0.05463320
PBANKA-0104100 0.10698392 0.000000000 0.000000000 0.021640058 0.01323152
PBANKA-0104900 0.15330358 0.040643918 0.047150266 0.096686040 0.08016202
PBANKA-0105100 0.00774803 0.000000000 0.000000000 0.000000000 0.01212389
PBANKA-0105200 0.14295074 0.090669292 0.195180247 0.390381118 0.10203677
PBANKA-0105300 0.07266638 0.035247576 0.083080416 0.026830263 0.08893071
PBANKA-0105500 0.05972304 0.130442176 0.613873789 0.124039039 0.06698287
PBANKA-0105600 0.10822754 0.303080159 0.124325455 0.169514333 0.18211011
PBANKA-0106100 0.08682023 0.000000000 0.037839217 0.049002485 0.05906248
PBANKA-0106300 0.01815899 0.000000000 0.007580943 0.002964005 0.01617340
PBANKA-0106500 0.06709366 0.160165980 0.103227974 0.026045686 0.29711821
PBANKA-0106600 0.06615049 0.041341810 0.011974030 0.090413046 0.08166804
PBANKA-0106900 0.06772833 0.099129853 0.058992669 0.401040855 0.09974455
PBANKA-0106950 0.07031790 0.010838894 0.008323748 0.062299847 0.04044479
PBANKA-0107100 0.17579265 0.059474584 0.032474136 0.119798580 0.10795614
PBANKA-0107300 0.52569711 0.140088244 0.000000000 0.452049173 0.43157921
PBANKA-0107400 0.40027934 0.554030211 0.028538986 0.179514374 0.30285506
PBANKA-0107500 0.06729382 0.074821209 0.023884962 0.041973749 0.10242388
PBANKA-0107600 0.10346987 0.295645683 0.107376132 0.291553393 0.09681055
PBANKA-0108200 0.10862989 0.032331520 0.101822888 0.088844686 0.07713661
PBANKA-0108500 0.02145669 0.030583685 0.024050668 0.031126013 0.02086511
PBANKA-0108600 0.24498462 0.045568380 0.056630631 0.095147870 0.18860540
PBANKA-0108700 0.39883605 0.152992706 0.123346730 0.108083282 0.35455198
PBANKA-0108800 0.08791660 0.022213910 0.000000000 0.016375691 0.04375594
PBANKA-0108900 0.03944358 0.012735216 0.017821829 0.063455344 0.06855602
dim(metadata(sce)$scmap_cell_index$subclusters)
[1]   50 6880
#saveRDS(pb_filtered_sce_orth, file="pb_filtered_sce_orthindex_20181109.rds")

Map to the index

scmapCell_results$wt$cells[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]          6554          6685          6163
 [2,]          6247          6528          6200
 [3,]          6734          6436          6466
 [4,]          6323          6588          6124
 [5,]          6468          6470          6871
 [6,]          6685          6323          6563
 [7,]          6470          6606          6456
 [8,]          6436          6614          6149
 [9,]          6515          6608          6494
[10,]          6614          6854          6647
## get cell indexes 
getcells <- scmapCell_results$wt$cells[1, ]
## exctract cells metadata from index
cdsce <- colData(sce)[getcells, ]
## extract similarities
topsim <- scmapCell_results$wt$similarities[1, ]
## get name of top cell matched
mutants.sce$topcell <- rownames(cdsce)
## get sex id
mutants.sce$topcell_ac <- cdsce$label.monocle_sex
## get coordinates of matched cell
mutants.sce$indexPC1 <- cdsce$label.UMAP_1
mutants.sce$indexPC2 <- cdsce$label.UMAP_2
#mutants.sce$pbpt <- cdsce$pseudotime
#mutants.sce$pbbulk <- cdsce$bulk
mutants.sce$topcell_sp <- mutants.sce$topcell_ac
mutants.sce$topsim <- topsim
mutants.sce$topcell_sp[mutants.sce$topsim < 0.4] <- "unassigned"
table(mutants.sce$topcell_sp)

Asexual_Early  Asexual_Late        Female          Male    unassigned 
          335           346           186           548          1302 
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$topcell_sp, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      89       2
  Asexual_Late    5     150       3
  Female          2      84      54
  Male          158      47       0
  unassigned     52     549     198
table(colData(mutants.sce)$topcell_sp, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   9  74  13   9  20  12  17  20   8  67        86
  Asexual_Late   14  21  37   8  36  45  21  43  20  22        79
  Female          1   2   7   2   0  17  39  44   3   6        65
  Male           64  51  14  41  25   0   0  34  12 104       203
  unassigned     65  92  63  33 152 181 184 195  34  47       256
#### TOP 3NN method

#This function makes a list of the PC means for each cell and then do.call below rbinds them into a dataframe called big_data

datalist = list()

for (i in colnames(scmapCell_results$wt$cells)) {
  
  getcellstest <- scmapCell_results$wt$cells[1:3, i]
  cdscetest <- colData(sce)[getcellstest, ]
  PC1mean <- mean(cdscetest$label.UMAP_1)
  PC2mean <- mean(cdscetest$label.UMAP_2)
  # ... make some data
  dat <- data.frame(i, PC1mean, PC2mean)
  dat$i <- i  # maybe you want to keep track of which iteration produced it?
  datalist[[i]] <- dat # add it to your list
}

big_data = do.call(rbind, datalist)
# or big_data <- dplyr::bind_rows(datalist)
# or big_data <- data.table::rbindlist(datalist)

test <- big_data[1, ]

df <- data.frame(X=colData(sce)$label.UMAP_1, Y=colData(sce)$label.UMAP_2, row.names = rownames(colData(sce)))

#the snap function snaps to the nearest cell in PC coordiantes
snap <- function(df, test){
  require(Biobase)
  d <- matchpt(as.matrix(df),
               as.matrix(data.frame(X=test$PC1mean,Y=test$PC2mean)))
  
  min_row <- rownames(d[d$distance==min(d$distance),])
  
  test$X_snap <- unique(df[min_row,"X"])
  test$Y_snap <- unique(df[min_row,"Y"])
  test$pb_cell <- min_row
  
  test
}

#this loops through each cell and in big_data and runs the snap function
datalist2 = list()
colnames(big_data) <- c("sample_id", "PC1mean", "PC2mean")
for (i in rownames(big_data)) {
  test <- big_data[i, ]
  coord <- snap(df, test)
  coord$i <- i
  datalist2[[i]] <- coord
}
big_data2 = do.call(rbind, datalist2)


table(rownames(big_data2)==rownames(colData(mutants.sce)))

TRUE 
2717 
allpbcd <- colData(sce)
allpbcd <- as.data.frame(allpbcd)
pbabsclust <- allpbcd[, c("label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex"), drop=FALSE]
pbabsclust$pb_sample_id <- rownames(pbabsclust)

# Now merge the pc cell asignments with their abs clust and get in the right order
big_data3 <- merge(big_data2, pbabsclust, by.x = "pb_cell", by.y = "pb_sample_id", all.x=TRUE, all.y=FALSE)
big_data4 <- big_data3[match(rownames(big_data2), big_data3$sample_id), ]


colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black")

ggplot(big_data4, aes(PC1mean, PC2mean)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed()


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

                     

ggplot(big_data4, aes(X_snap, Y_snap)) +
  geom_point(col = big_data4$label.pt_id_cols) +
                     theme_void() +
                     coord_fixed() 


#+ geom_point(aes(colour=factor(big_data4$label.label.pt_id_cols))) + scale_color_manual(values = colors) 

##add info to SCE and save colData, to be an assigned cell all 3NN must have a cos sim >0.4
scmapCell_results$wt$similarities[, 1:3]
      SC26779_5_100 SC26779_5_101 SC26779_5_102
 [1,]     0.2654243     0.3283723     0.4455592
 [2,]     0.2657229     0.3322655     0.4476295
 [3,]     0.2649363     0.3346425     0.4463425
 [4,]     0.2685002     0.3314723     0.4455779
 [5,]     0.2655940     0.3347640     0.4463982
 [6,]     0.2654118     0.3351348     0.4472700
 [7,]     0.2659329     0.3289516     0.4482864
 [8,]     0.2683255     0.3303473     0.4451670
 [9,]     0.2668498     0.3284948     0.4503529
[10,]     0.2664087     0.3284307     0.4486978
topsim1 <- scmapCell_results$wt$similarities[1, ]
topsim2 <- scmapCell_results$wt$similarities[2, ]
topsim3 <- scmapCell_results$wt$similarities[3, ]

table(big_data4$sample_id==rownames(colData(mutants.sce)))

TRUE 
2717 
#pfobj$pb_cell <- big_data4$pb_cell
#pfobj$PC1mean <- big_data4$PC1mean
bd4 <- big_data4[, c("pb_cell", "sample_id", "PC1mean", "PC2mean", "X_snap", "Y_snap", "label.pt_id_cols", "label.identity_name_updated", "label.monocle_sex")]

colData(mutants.sce) <- cbind(colData(mutants.sce), bd4)

mutants.sce$topsim1 <- topsim1
mutants.sce$topsim2 <- topsim2
mutants.sce$topsim3 <- topsim3
mutants.sce$stage_pred <- big_data4$label.monocle_sex
mutants.sce$stage_pred[mutants.sce$topsim1 < 0.4 | mutants.sce$topsim2 < 0.4 | mutants.sce$topsim3 < 0.4] <- "unassigned"
table(mutants.sce$stage_pred)

Asexual_Early  Asexual_Late   Bipotential        Female          Male    unassigned 
          325           345             1           182           546          1318 
#write.csv(bd4, "pfcellassignmentswithmean3nn_20181029.csv")
#write.csv(colData(pfobj), "pf3d7100scmapclusts2methodindexn100_20190107.csv")
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$stage_pred, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   1      81       2
  Asexual_Late    3     153       3
  Bipotential     0       1       0
  Female          2      83      52
  Male          156      47       0
  unassigned     55     554     200
table(colData(mutants.sce)$stage_pred, colData(mutants.sce)$label.identity_name_updated)
               
                fd1 fd2 fd3 fd4 gd1 md1 md2 md3 md4 md5 wild-type
  Asexual_Early   7  73  11   9  20  10  15  20   7  68        85
  Asexual_Late   16  22  39   8  34  46  23  41  20  21        75
  Bipotential     0   0   0   0   0   0   0   0   0   0         1
  Female          1   2   7   2   0  16  39  44   3   6        62
  Male           64  51  14  41  25   0   0  33  12 104       202
  unassigned     65  92  63  33 154 183 184 198  35  47       264

make final plot with MCA data below

## Read in MCA data
pheno <- read.csv("../scmap/allpb10x_pheno.csv")
## extract rows needed for plotting
df_plot <- pheno[,c("PC2_3d", "PC3_3d", "absclust3")]
df_plot$experiment <- df_plot$absclust3

## extract rows needed for plotting from mapped object
df_plot_pm <- as.data.frame(colData(pm_ss2_field.sce.orth))
df_plot_pm <- df_plot_pm[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pm$experiment <- "pm"
colnames(df_plot_pm) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## extract rows needed for plotting from mapped object
df_plot_pf <- as.data.frame(colData(pf_ss2_field.sce.orth))
df_plot_pf <- df_plot_pf[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pf$experiment <- "pf"
colnames(df_plot_pf) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## bind together
df_plot <- rbind(df_plot, df_plot_pf, df_plot_pm)

colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black",
            "pm" = "#dc65a4",
            "pf" = "#24245f")

## add alpha for plotting
df_plot$alpha[!df_plot$experiment == "pm"] <- 0.5
df_plot$alpha[df_plot$experiment == "pm"] <- 1
df_plot$alpha[df_plot$experiment == "pf"] <- 1

##plot
scmap_pca <- ggplot(df_plot, aes(x=PC2_3d, y = PC3_3d,colour=experiment, alpha = alpha)) + 
  geom_point() +
  theme_void() +
  scale_color_manual(values = colors) +
  ## remove alpha scale
  scale_alpha_continuous(guide=FALSE)
  ## draw ring around field samples
  #geom_point(data=df_plot[df_plot$experiment == "pm", ], pch=21, fill=NA, size=2, colour="black", stroke=1) +
  ## make non-field samples more opaque
  #geom_point(data=df_plot[-df_plot$experiment == "pm", ], alpha = 0.2)

## view
scmap_pca_2 <- scmap_pca + 
  guides(colour=guide_legend(override.aes = list(size=4)))

scmap_pca_2

save

#ggsave("../images_to_export/field_samples_scmap.png", plot = scmap_pca_2, device = "png", path = NULL, scale = 1, width = 15, height = 10, units = "cm", dpi = 300, limitsize = TRUE)

Overlap and validation

11. Save and Export

save

Save environment

## This saves everything in the global environment for easy recall later
#save.image(file = "GCSKO_merge.RData")
#load(file = "GCSKO_merge.RData")

Save object(s)

## Save an object to a file
saveRDS(tenx.justwt.integrated.sex, file = "../data_to_export/tenx.justwt.integrated.sex.RDS")
## Restore the object
#readRDS(file = "../data_to_export/tenx.mutant.integrated.sex.RDS")

## save integrated object to file
saveRDS(tenx.justwt.integrated, file = "../data_to_export/tenx.justwt.integrated.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## save monocle object
saveRDS(monocle.object.all, file = "../data_to_export/monocle.object.all.RDS") 
## restore the object
#monocle.object.all <- readRDS("../data_to_export/monocle.object.all.RDS")

## save integrated object to file
#saveRDS(GCSKO_mutants, file = "../data_to_export/GCSKO_mutants.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## extract UMAP coordinates and metadata
## extract metadata
mca_website_df <- tenx.justwt.integrated@meta.data

## add umap - merge on row names and then make sure row names are not dropped or added
mca_website_df <- transform(merge(mca_website_df, tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings, by=0, all=TRUE), row.names=Row.names, Row.names=NULL)

## send this to sunil:
# ggplot(mca_website_df, aes(x = UMAP_1, y = UMAP_2)) +
# geom_point(col = mca_website_df$pt_id_cols) +
# theme_void() +
# coord_fixed()

## export
write.csv(mca_website_df, file = "../data_to_export/mca_website_df.csv")

Clean up

#rm(ss2_wt_cells)
#rm(tenx.justwt.integrated)
#rm(tenx.justwt.list)

final figure construction

Cowplot(plot_grid), patchwork(wrap_plots), and ggpubr can all allow multiple plots to be plotted together.

## A
# umap_id_pt
## B
# marker gene expression
## C
# Mutant gene expression
## D
# Modules

#Figure_A <- grid.arrange(arrangeGrob(QC_composite_plot, QC_mito_violin, QC_mito_graph, QC_by_genotype, mapping_rate_plot), nrow=3), nrow=2, heights=c(10,2))

## cowplot method
## can use this for labels: toupper(letters)[1:10]

## C. Mutant genes
mutant_genes_figure <- plot_grid(
                                 ## marker genes starts
                                 marker_gene_plot_FAMB,
                                 marker_gene_plot_MSP8,
                                 marker_gene_plot_MSP1,
                                 marker_gene_plot_AP2G,
                                 marker_gene_plot_CCP2,
                                 marker_gene_plot_MG1,
                                 ## mutant genes starts  
                                 marker_gene_plot_gd1,
                                 marker_gene_plot_md1,
                                 marker_gene_plot_md2,
                                 marker_gene_plot_md3,
                                 marker_gene_plot_md4, 
                                 marker_gene_plot_md5,
                                 marker_gene_plot_fd1,
                                 marker_gene_plot_fd2,
                                 marker_gene_plot_fd3,
                                 marker_gene_plot_fd4, 
  label_size = 1, 
  nrow = 4)

## labels as uppercase letters:
#c(toupper(letters)[2:17])
# labels as roman numerals:
# c(tolower(as.roman(c(2:17))

Figure_publication <- plot_grid(umap_id_pt + theme(plot.margin = unit(c(0, 0, 0, 0), "cm")), 
                                mutant_genes_figure,
                                ## add empty plot to give spacing
                                ggplot() + theme_void(),
                                labels = c('A', 'B'), 
                                label_size = 12, 
                                ncol = 2, 
                                nrow=2, 
                                rel_heights = c(1, 1, 4), 
                                rel_widths = c(1, 2, 3))

Figure_publication

save

ggsave("../images_to_export/Figure_C.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
layout <- "
AAABBB
CCDDEE
FFGGHH
IIJJKK
"

Figure_publication_A <- (composition_umap_10x + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) +
(composition_umap_ss2 + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) + 
plot_layout(ncol = 2)

Figure_publication <- Figure_publication_A +
#(UMAP_hoo + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Asexual Cycle Real Timepoint")) +
#(UMAP_kasia + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Gametocytogenesis Real Timepoint")) +
  ## marker genes
marker_gene_plot_FAMB +
marker_gene_plot_MSP8 +
marker_gene_plot_MSP1 +
marker_gene_plot_CDPK5 +
marker_gene_plot_AP2G +
marker_gene_plot_CCP2 +
marker_gene_plot_MG1 +
marker_gene_plot_ORC1 +
marker_gene_plot_MCM4 +
  ## mutant genes starts  
#marker_gene_plot_gd1 +
#marker_gene_plot_md1 +
#marker_gene_plot_md2 +
#marker_gene_plot_md3 +
#marker_gene_plot_md4 + 
#marker_gene_plot_md5 +
#marker_gene_plot_fd1 +
#marker_gene_plot_fd2 +
#marker_gene_plot_fd3 +
#marker_gene_plot_fd4 + 
plot_layout(ncol = 6, 
            widths = c(1, 1, 1, 1, 1 ,1),
            heights = c(2, 1, 1, 1),
            design = layout
            )

Figure_publication

save

ggsave("../images_to_export/Figure_S2.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

Appendix

Session Info

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
 [1] stats4    parallel  grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] colourvalues_0.3.7          readxl_1.3.1                destiny_3.2.0               circlize_0.4.12            
 [5] gganimate_1.0.7             shiny_1.5.0                 monocle3_0.2.3.0            SingleCellExperiment_1.10.1
 [9] SummarizedExperiment_1.18.2 DelayedArray_0.14.1         matrixStats_0.57.0          GenomicRanges_1.40.0       
[13] GenomeInfoDb_1.24.2         IRanges_2.22.2              S4Vectors_0.26.1            Biobase_2.48.0             
[17] BiocGenerics_0.34.0         Nebulosa_1.2.0              reshape2_1.4.4              Hmisc_4.4-1                
[21] Formula_1.2-4               survival_3.2-7              lattice_0.20-41             gridExtra_2.3              
[25] dplyr_1.0.2                 patchwork_1.0.1             ggplot2bdc_0.3.2            cowplot_1.1.0              
[29] ggpubr_0.4.0                ggplot2_3.3.2               viridis_0.5.1               viridisLite_0.3.0          
[33] Seurat_3.2.2                colorspace_1.4-1           

loaded via a namespace (and not attached):
  [1] ggthemes_4.2.4            coda_0.19-4               tidyr_1.1.2               knitr_1.30               
  [5] irlba_2.3.3               data.table_1.13.2         rpart_4.1-15              RCurl_1.98-1.2           
  [9] generics_0.0.2            callr_3.5.1               leidenbase_0.1.2          usethis_1.6.3            
 [13] RANN_2.6.1                proxy_0.4-24              future_1.19.1             spatstat.data_1.4-3      
 [17] httpuv_1.5.4              assertthat_0.2.1          gifski_0.8.6              xfun_0.18                
 [21] hms_0.5.3                 evaluate_0.14             promises_1.1.1            DEoptimR_1.0-8           
 [25] fansi_0.4.1               progress_1.2.2            DBI_1.1.0                 igraph_1.2.6             
 [29] htmlwidgets_1.5.2         spdep_1.1-5               purrr_0.3.4               ellipsis_0.3.1           
 [33] RSpectra_0.16-0           crosstalk_1.1.0.1         ks_1.12.0                 backports_1.1.10         
 [37] deldir_0.1-29             vctrs_0.3.4               TTR_0.24.2                remotes_2.2.0            
 [41] ROCR_1.0-11               abind_1.4-5               RcppEigen_0.3.3.7.0       withr_2.3.0              
 [45] grr_0.9.5                 robustbase_0.93-7         checkmate_2.0.0           vcd_1.4-8                
 [49] sctransform_0.3.1         xts_0.12.1                prettyunits_1.1.1         mclust_5.4.7             
 [53] goftest_1.2-2             cluster_2.1.0             lazyeval_0.2.2            laeken_0.5.1             
 [57] crayon_1.3.4              units_0.6-7               slam_0.1-47               pkgconfig_2.0.3          
 [61] labeling_0.4.2            tweenr_1.0.1              nlme_3.1-149              pkgload_1.1.0            
 [65] nnet_7.3-14               devtools_2.3.2            rlang_0.4.8               globals_0.13.1           
 [69] lifecycle_0.2.0           miniUI_0.1.1.1            rsvd_1.0.3                cellranger_1.1.0         
 [73] rprojroot_1.3-2           polyclip_1.10-0           RcppHNSW_0.3.0            lmtest_0.9-38            
 [77] Matrix_1.2-18             raster_3.3-13             carData_3.0-4             Matrix.utils_0.9.8       
 [81] boot_1.3-25               zoo_1.8-8                 base64enc_0.1-3           ggridges_0.5.2           
 [85] GlobalOptions_0.1.2       processx_3.4.4            pheatmap_1.0.12           png_0.1-7                
 [89] bitops_1.0-6              KernSmooth_2.23-17        DelayedMatrixStats_1.10.1 classInt_0.4-3           
 [93] shape_1.4.5               stringr_1.4.0             jpeg_0.1-8.1              rstatix_0.6.0            
 [97] ggsignif_0.6.0            scales_1.1.1              memoise_1.1.0             magrittr_2.0.1           
[101] plyr_1.8.6                hexbin_1.28.1             ica_1.0-2                 gdata_2.18.0             
[105] zlibbioc_1.34.0           compiler_4.0.3            RColorBrewer_1.1-2        pcaMethods_1.80.0        
[109] fitdistrplus_1.1-1        cli_2.1.0                 LearnBayes_2.15.1         XVector_0.28.0           
[113] listenv_0.8.0             pbapply_1.4-3             ps_1.4.0                  htmlTable_2.1.0          
[117] ggplot.multistats_1.0.0   MASS_7.3-53               mgcv_1.8-33               tidyselect_1.1.0         
[121] stringi_1.5.3             forcats_0.5.0             yaml_2.2.1                latticeExtra_0.6-29      
[125] ggrepel_0.8.2             pbmcapply_1.5.0           tools_4.0.3               future.apply_1.6.0       
[129] rio_0.5.16                rstudioapi_0.11           foreign_0.8-80            smoother_1.1             
[133] scatterplot3d_0.3-41      farver_2.0.3              Rtsne_0.15                digest_0.6.27            
[137] BiocManager_1.30.10       Rcpp_1.0.6                car_3.0-10                broom_0.7.2              
[141] later_1.1.0.1             RcppAnnoy_0.0.16          httr_1.4.2                sf_0.9-6                 
[145] fs_1.5.0                  tensor_1.5                ranger_0.12.1             reticulate_1.18          
[149] splines_4.0.3             uwot_0.1.8                expm_0.999-5              spatstat.utils_1.17-0    
[153] sp_1.4-4                  spData_0.3.8              plotly_4.9.2.1            sessioninfo_1.1.1        
[157] xtable_1.8-4              jsonlite_1.7.1            spatstat_1.64-1           testthat_2.3.2           
[161] R6_2.5.0                  gmodels_2.18.1            pillar_1.4.6              htmltools_0.5.1.1        
[165] mime_0.9                  glue_1.4.2                fastmap_1.0.1             VIM_6.1.0                
[169] class_7.3-17              codetools_0.2-16          utf8_1.1.4                pkgbuild_1.1.0           
[173] mvtnorm_1.1-1             tibble_3.0.4              curl_4.3                  leiden_0.3.3             
[177] gtools_3.8.2              zip_2.1.1                 openxlsx_4.2.2            limma_3.44.3             
[181] rmarkdown_2.5             desc_1.2.0                munsell_0.5.0             e1071_1.7-4              
[185] GenomeInfoDbData_1.2.3    haven_2.3.1               gtable_0.3.0             

Expression plots

Expression - raw - Viridis

## find a good ring marker, to see if there is a better one than the ones reported
#markers_ring <- FindMarkers(tenx.justwt.integrated, ident.1 = c("4", "5", "16", "11", "7", "3", "9", "0", "22"))
#head(markers_ring)

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(ccp2), "(Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))
Error in italic(ccp2) : could not find function "italic"

Expression - raw - purple


marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("CCP2 (Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0416100", coord.fixed = TRUE, 
                                    #min.cutoff = "q1", 
                                    dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MG1 (Male)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1437500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("AP2G (Commitment)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0831000", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP1 (Schizont)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1102200", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP8 (Asexual)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1101300", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("SBP1 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0722600", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("Fam-b2 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0711900", coord.fixed = TRUE, 
                                      #min.cutoff = "q1", 
                                      dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("(HSP70; Reporter)","\n", "PBANKA_0711900")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)
font family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font databasefont family 'Arial' not found in PostScript font database
marker_gene_plot_all

Expression - data - purple

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

Density Plots

Density - purple

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=marker_gene_ramp) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=marker_gene_ramp) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density -viridis

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

Density - viridis

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
UMAP_composite_mutant_genes

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "wkde", slot = 'data')

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_color_continuous_sequential(palette = "Purples 2") + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + 
                               coord_fixed() + 
                               theme_void() + 
                               labs(title = paste("md2")) + scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
## old colour scale: scale_colour_gradientn(colours=marker_gene_ramp )

UMAP_composite_mutant_genes

LS0tCnN1YnRpdGxlOiAnR2FtZXRvY3l0ZSBEZXZlbG9wbWVudCBpbiA8aT5QbGFzbW9kaXVtIGJlcmdoZWk8L2k+Jwp0aXRsZTogfAogICFbXSguLi9HQ1NLT19sb2dvLmpwZyl7d2lkdGg9MzAwcHh9ICAKICBNZXJnaW5nIFNtYXJ0LXNlcTIgYW5kIDEwWCBEYXRhc2V0cyAtIHdpbGQtdHlwZSBvbmx5CmF1dGhvcjogIltBbmRyZXcgUnVzc2VsbF0oaHR0cHM6Ly9hamNydXNzZWxsLndpeHNpdGUuY29tL215c2l0ZS9hYm91dCkiCmluc3RpdHV0ZTogV2VsbGNvbWUgU2FuZ2VyIEluc3RpdHV0ZQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlQiAlZCwgJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICAjdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KKioqCiMgMS4gSW50cm9kdWN0aW9uIGFuZCBBaW1zIHsudGFic2V0fQoKV2UgaGF2ZSBxdWFsaXR5LWNvbnRyb2xsZWQgdGhlIDEwWCBkYXRhIGFuZCB0aGUgU1MyIGRhdGEgYW5kIG5vdyBhcmUgbGVmdCB3aXRoIHRoZSBmb2xsb3dpbmcgb2JqZWN0czoKCjEwWCA1SyBkYXRhIC0gcGJfc2V4X2ZpbHRlcmVkCgoxMFggMzBLIGRhdGEgLSBwYl8zMGtfc2V4X2ZpbHRlcmVkIAoKU1MyIG11dGFudCBkYXRhIC0gc3MyX211dGFudHNfZmluYWwKCiMgMi4gUmVhZCBpbiB0aGUgZGF0YSAgey50YWJzZXR9CgojIyMgTG9hZC9JbnN0YWxsIHRoZSBSZXF1aXJlZCBQYWNrYWdlcwoKYGBge3IgbG9hZCBwYWNrYWdlcywgZWNobyA9IEZBTFNFfQojIyBDUkFOIHBhY2thZ2VzCgojIyBQYXRod29yayBpcyBuZWVkZWQgdG8gc3RpY2ggcGxvdHMgdG9nZXRoZXIgdXNpbmcgJysnCmlmKHJlcXVpcmUoInBhdGNod29yayIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgicGF0Y2h3b3JrIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIHBhdGNod29yayIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwYXRjaHdvcmsiKQogICAgaWYocmVxdWlyZShwYXRjaHdvcmspKXsKICAgICAgICBwcmludCgicGF0Y2h3b3JrIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgcGF0Y2h3b3JrIikKICAgIH0KfQoKIyMgdmlyaWRpcyBhbGxvd3MgZGlmZmVyZW50IGNvbG91cnMgdG8gYmUgYWRkZWQgdG8gcGxvdHMKaWYocmVxdWlyZSgidmlyaWRpcyIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgidmlyaWRpcyBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCB2aXJpZGlzIikKICAgIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQogICAgaWYocmVxdWlyZSh2aXJpZGlzKSl7CiAgICAgICAgcHJpbnQoInZpcmlkaXMgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCB2aXJpZGlzIikKICAgIH0KfQoKIyMgU2V1cmF0IGlzIG5lZWRlZCBmb3IgbW9zdCBvZiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJTZXVyYXQiLCBxdWlldGx5ID0gVFJVRSkpewogICAgcHJpbnQoIlNldXJhdCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBTZXVyYXQiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiU2V1cmF0IikKICAgIGlmKHJlcXVpcmUoU2V1cmF0KSl7CiAgICAgICAgcHJpbnQoIlNldXJhdCBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIFNldXJhdCIpCiAgICB9Cn0KCiMjIGNvd3Bsb3QgaXMgbmVlZGVkIGZvciBwbG90cyBpbiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJjb3dwbG90IikpewogICAgcHJpbnQoImNvd3Bsb3QgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgY293cGxvdCIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikKICAgIGlmKHJlcXVpcmUoY293cGxvdCkpewogICAgICAgIHByaW50KCJjb3dwbG90IGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgY293cGxvdCIpCiAgICB9Cn0KCiMjIGdyaWRFeHRyYSBpcyBuZWVkZWQgZm9yIGdyaWQgZ3JhcGhpY3MgdG8gcGxvdCBtdWx0aXBsZSBwbG90cyBpbiB0aGUgc2FtZSB2aWV3CmlmKHJlcXVpcmUoImdyaWRFeHRyYSIpKXsKICAgIHByaW50KCJncmlkRXh0cmEgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgZ3JpZEV4dHJhIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIpCiAgICBpZihyZXF1aXJlKGdyaWRFeHRyYSkpewogICAgICAgIHByaW50KCJncmlkRXh0cmEgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkRXh0cmEiKQogICAgfQp9CgojIyBncmlkIGlzIG5lZWRlZCBmb3IgZ3JpZC5hcnJhbmdlIGZ1bmN0aW9uIHRvIGNoYW5nZSBzaXplIG9mIHRpdGxlCmlmKHJlcXVpcmUoImdyaWQiKSl7CiAgICBwcmludCgiZ3JpZCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBncmlkIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWQiKQogICAgaWYocmVxdWlyZShncmlkKSl7CiAgICAgICAgcHJpbnQoImdyaWQgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkIikKICAgIH0KfQoKIyNmb3IgZG9pbmcgYnVsayBjb3JyZWxhdGlvbiBjYWxjdWxhdGlvbnMKaWYocmVxdWlyZSgiSG1pc2MiKSl7CiAgICBwcmludCgiSG1pc2MgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgSG1pc2MiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQogICAgaWYocmVxdWlyZShIbWlzYykpewogICAgICAgIHByaW50KCJIbWlzYyBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIEhtaXNjIikKICAgIH0KfQoKIyMgcmVzaGFwZTIgdG8gbWVsdCBkYXRhZnJhbWVzIGZvciBwbG90dGluZzoKaWYocmVxdWlyZSgicmVzaGFwZTIiKSl7CiAgICBwcmludCgicmVzaGFwZTIgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgcmVzaGFwZTIiKQogICAgaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKQogICAgaWYocmVxdWlyZShyZXNoYXBlMikpewogICAgICAgIHByaW50KCJyZXNoYXBlMiBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIHJlc2hhcGUyIikKICAgIH0KfQoKIyMgdG8gd29yayB3aXRoIGRhdGEgZnJhbWVzOgppZihyZXF1aXJlKCJkcGx5ciIpKXsKICAgIHByaW50KCJkcGx5ciBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBkcGx5ciIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiAgICBpZihyZXF1aXJlKGRwbHlyKSl7CiAgICAgICAgcHJpbnQoImRwbHlyIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgZHBseXIiKQogICAgfQp9CgojIyBub24tQ1JBTiBwYWNrYWdlcwoKIyMgdG8gbWFrZSBkZW5zaXR5IHBsb3RzIHNob3dpbmcgZ2VuZSBleHByZXNzaW9uCmlmKHJlcXVpcmUoIk5lYnVsb3NhIikpewogICAgcHJpbnQoIk5lYnVsb3NhIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIE5lYnVsb3NhIikKICAgIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigicG93ZWxsZ2Vub21pY3NsYWIvTmVidWxvc2EiKQogICAgaWYocmVxdWlyZShOZWJ1bG9zYSkpewogICAgICAgIHByaW50KCJOZWJ1bG9zYSBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIE5lYnVsb3NhIikKICAgIH0KfQoKIyMgbW9ub2NsZTMgdG8gY2FsY3VsYXRlIHBzZXVkb3RpbWU6CmlmKHJlcXVpcmUoIm1vbm9jbGUzIikpewogICAgcHJpbnQoIm1vbm9jbGUzIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoIlBsZWFzZSBpbnN0YWxsIG1vbm9jbGUzIChodHRwczovL2NvbGUtdHJhcG5lbGwtbGFiLmdpdGh1Yi5pby9tb25vY2xlMy9kb2NzL2luc3RhbGxhdGlvbi8pIikKfQoKIyMgc2V0IHRoZSBzZWVkIGZvciBib3RoIHRoZSBtaXh0dXJlIG1vZGVscyBhbmQgYWxzbyBmb3IgdGhlIHNhbXBsZSBmdW5jdGlvbiBsYXRlciBvbjoKc2V0LnNlZWQoLTkyNDk3KQpgYGAKCiMjIyBSZWFkIGluIHRoZSBEYXRhCgpzY3JlZW4gaGl0cwpgYGB7cn0KIyMgRURJVCAtIGNoYW5nZSB0aGlzIHRvIHRoZSBleGNlbCB0YWJsZSBvbmNlIHdlIGhhdmUgaXQgZmluYWxpemVkIGZvciB0aGUgc2NyZWVuCnNjcmVlbl9oaXRzIDwtIGMoIlBCQU5LQS0wNTE2MzAwIiwKIlBCQU5LQS0xMjE3NzAwIiwKIlBCQU5LQS0wNDA5MTAwIiwKIlBCQU5LQS0xMDM0MzAwIiwKIlBCQU5LQS0xNDM3NTAwIiwKIlBCQU5LQS0wODI3NTAwIiwKIlBCQU5LQS0wODI0MzAwIiwKIlBCQU5LQS0xNDI2OTAwIiwKIlBCQU5LQS0wMTA1MzAwIiwKIlBCQU5LQS0wOTIxMTAwIiwKIlBCQU5LQS0xMDAyNDAwIiwKIlBCQU5LQS0wODI5NDAwIiwKIlBCQU5LQS0xMzQ3MjAwIiwKIlBCQU5LQS0wODI4MDAwIiwKIlBCQU5LQS0wOTAyMzAwIiwKIlBCQU5LQS0xNDE4MTAwIiwKIlBCQU5LQS0xNDM1MjAwIiwKIlBCQU5LQS0xNDU0ODAwIiwKIlBCQU5LQS0wNzEyMzAwIiwKIlBCQU5LQS0wNDEwNTAwIiwKIlBCQU5LQS0xMTQ0ODAwIiwKIlBCQU5LQS0xMjMxNjAwIiwKIlBCQU5LQS0wNTAzMjAwIiwKIlBCQU5LQS0wMzA4OTAwIiwKIlBCQU5LQS0xMjE0NzAwIiwKIlBCQU5LQS0wNzA5OTAwIiwKIlBCQU5LQS0wMzExOTAwIiwKIlBCQU5LQS0wNzE2NTAwIiwKIlBCQU5LQS0xNDQ3OTAwIiwKIlBCQU5LQS0wMTAyMjAwIiwKIlBCQU5LQS0wNzEzNTAwIiwKIlBCQU5LQS0wMTAyNDAwIiwKIlBCQU5LQS0xMzAyNzAwIiwKIlBCQU5LQS0xMjM1OTAwIiwKIlBCQU5LQS0wNDAxMTAwIiwKIlBCQU5LQS0wNDEzNDAwIiwKIlBCQU5LQS0xMTI2OTAwIiwKIlBCQU5LQS0xNDI1OTAwIiwKIlBCQU5LQS0wNDE4MzAwIiwKIlBCQU5LQS0xNDY0NjAwIiwKIlBCQU5LQS0wODA2MDAwIikKYGBgCgpSZWFkIGluIGdlbmUgYW5ub3RhdGlvbnMKYGBge3J9CmdlbmVfYW5ub3RhdGlvbnMgPC0gcmVhZC50YWJsZSgiLi4vZGF0YS9SZWZlcmVuY2UvR2VuZXNCeVRheG9uX1N1bW1hcnkuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKZGltKGdlbmVfYW5ub3RhdGlvbnMpCgojIyBjb252ZXJ0IF8gdG8gLQpnZW5lX2Fubm90YXRpb25zJEdlbmUuSUQgPC0gZ3N1YigiXyIsICItIiwgZ2VuZV9hbm5vdGF0aW9ucyRHZW5lLklEKQpgYGAKCmxvYWQgaW4gZGF0YXNldHMKYGBge3J9CiMjIGxvYWQgdGhlIDEwWCBkYXRhc2V0CnBiX3NleF9maWx0ZXJlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC9wYl9zZXhfZmlsdGVyZWQuUkRTIikKIyMgbG9hZCB0aGUgU1MyIGRhdGFzZXQKc3MyX211dGFudHNfZmluYWwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvc3MyX211dGFudHNfZmluYWwuUkRTIikKCiMjIGluc3BlY3QKcGFzdGUoIjEweCBkYXRhc2V0IikKcGJfc2V4X2ZpbHRlcmVkCnBhc3RlKCJTbWFydC1zZXEyIGRhdGFzZXQiKQpzczJfbXV0YW50c19maW5hbApwYXN0ZSgiVGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBTbWFydC1zZXEyIGRhdGFzZXQgaXM6IikKdGFibGUoc3MyX211dGFudHNfZmluYWxAbWV0YS5kYXRhJGdlbm90eXBlKQpgYGAKCiMgMy4gTWVyZ2luZyB0aGUgU21hcnQtc2VxMiBhbmQgMTBYIERhdGEgey50YWJzZXR9CgojIyMgUHJlcGFyZSBkYXRhCgpgYGB7ciBpbnRlZ3JhdGlvbiAxMHggc2V0dXB9CiMjIGV4dHJhY3QgMTB4IGRhdGEKdGVueF81a19jb3VudHMgPC0gYXMubWF0cml4KHBiX3NleF9maWx0ZXJlZEBhc3NheXMkUk5BQGNvdW50cykKdGVueF81a19waGVubyA8LSBwYl9zZXhfZmlsdGVyZWRAbWV0YS5kYXRhCgojIyBDcmVhdGUgZnJlc2ggb2JqZWN0CnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gdGVueF81a19jb3VudHMsIG1ldGEuZGF0YSA9IHRlbnhfNWtfcGhlbm8sIG1pbi5jZWxscyA9IDAsIG1pbi5mZWF0dXJlcyA9IDAsIHByb2plY3QgPSAiR0NTS08iKQoKIyMgYWRkIGV4cGVyaW1lbnQgbWV0YSBkYXRhCnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZUBtZXRhLmRhdGEkZXhwZXJpbWVudCA8LSAidGVueF81ayIKCiMjIGluc3BlY3QKdGVueF81a19jb3VudHNfdG9faW50ZWdyYXRlCmBgYAoKV2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIG11dGFudCBkYXRhIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgMTBYIGRhdGEuIHRoZSAxMFggZGF0YSBoYXMgZmV3ZXIgZ2VuZXMgcmVwcmVzZW50ZWQgc28gd2UgbmVlZCB0byBmaW5kIHRoZSBpbnRlcnNlY3Qgb2YgdGhlIHR3byBiZWZvcmUgaW50ZWdyYXRpb24uCmBgYHtyIGludGVncmF0aW9uIHNzMiBzZXR1cH0KIyMgZXh0cmFjdCBTUzIgZGF0YSAKbXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24gPC0gYXMubWF0cml4KHNzMl9tdXRhbnRzX2ZpbmFsQGFzc2F5cyRSTkFAY291bnRzKQptdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uIDwtIHNzMl9tdXRhbnRzX2ZpbmFsQG1ldGEuZGF0YQoKIyMgY2hhbmdlIGNvdW50cyBzbyB0aGUgOnJSTkEgYW5kIDp0Uk5BIGFyZSBub3QgdGhlcmU6CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCI6bmNSTkEiLCAiIiwgZ3N1YigiOnJSTkEiLCAiIiwgZ3N1YigiOnRSTkEiLCAiIiwgcm93bmFtZXMobXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pKSkpCgojIyBjaGFuZ2UgdGhlIGdlbmUgbmFtZXMgc28gdGhhdCB0aGV5IGFyZSAtIHJhdGhlciB0aGFuIF86CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCJfIiwgIi0iLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpCgojIyBjYWxjdWxhdGUgaG93IG1hbnkgb2YgdGhlIGdlbmVzIG92ZXJsYXAgLSAxMHggZG9lcyBzdGFydCBvdXQgd2l0aCA1MDk4IHZzIDUyNDUKZ2VuZXNfaW5fdGVueF9kYXRhc2V0IDwtIGludGVyc2VjdChyb3duYW1lcyh0ZW54XzVrX2NvdW50cyksIHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSkKIyMgcHJpbnQgbnVtYmVyIG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCiMjIHN1YnNldCB0aGUgbXV0YW50IGNvdW50cyB0byBjb250YWluIG9ubHkgMTB4IGdlbmVzCm11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uIDwtIG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uW3doaWNoKHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSAlaW4lIGdlbmVzX2luX3RlbnhfZGF0YXNldCksIF0KIyMgcHJpbnQgcmVzdWx0IG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCgojIyBtYWtlIFNldXJhdCBvYmplY3Q6CkdDU0tPX211dGFudHMgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uLCBtZXRhLmRhdGEgPSBtdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uLCBtaW4uY2VsbHMgPSAwLCBtaW4uZmVhdHVyZXMgPSAwLCBwcm9qZWN0ID0gIkdDU0tPIikKCiMjIGFkZCBleHBlcmltZW50IG1ldGEgZGF0YQpHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRleHBlcmltZW50IDwtICJtdXRhbnRzIgoKIyMgaW5zcGVjdApHQ1NLT19tdXRhbnRzCmBgYAoKYGBge3J9CiMjIGRvdWJsZSBjaGVjayB0aGF0IHRoaXMgaXMgdGhlIHNhbWUgbnVtYmVyIG9mIGdlbmVzCiMjIHN1YnNldCBjb3VudHMgc28gdGhhdCBvbmx5IGdlbmVzIHJlcHJlc2VudGVkIGluIHRoZSBvdGhlciB0d28gb2JqZWN0cyBhcmUgdGhlcmU6Cmxlbmd0aChpbnRlcnNlY3Qocm93bmFtZXModGVueF81a19jb3VudHMpLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpKQpgYGAKCklNUE9SVEFOVCAtIHRoaXMgbmV4dCBzdGVwIGlzIGRpZmZlcmVudCB0byBHQ1NLT19tZXJnZSBhcyBpdCBzdWJzZXRzIHRoZSBzbWFydC1zZXEyIGRhdGEgaW50byB3aWxkLXR5cGUgb25seS4gCmBgYHtyfQojIyBzdWJzZXQgd3Qgb24gc3MyIGRhdGE6CnNzMl93dF9jZWxscyA8LSByb3duYW1lcyhHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YVtHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRnZW5vdHlwZSA9PSAiV1QiLCBdKQpHQ1NLT19tdXRhbnRzX3d0b25seSA8LSBzdWJzZXQoR0NTS09fbXV0YW50cywgY2VsbHMgPSBzczJfd3RfY2VsbHMpCmBgYAoKY3JlYXRlIGxpc3QgYW5kIG5vcm1hbGlzZToKYGBge3IgaW50ZWdyYXRpb24gbm9ybWFsaXNlfQojIyBtYWtlIGxpc3QKdGVueC5qdXN0d3QubGlzdCA8LSBsaXN0KHRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSwgR0NTS09fbXV0YW50c193dG9ubHkpCgojIyBwcmVwYXJlIGRhdGEKZm9yIChpIGluIDE6bGVuZ3RoKHRlbnguanVzdHd0Lmxpc3QpKSB7CiAgICB0ZW54Lmp1c3R3dC5saXN0W1tpXV0gPC0gTm9ybWFsaXplRGF0YSh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHZlcmJvc2UgPSBGQUxTRSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgCiAgICAgICAgbmZlYXR1cmVzID0gMjAwMCwgdmVyYm9zZSA9IEZBTFNFKQogICAgYWxsLmdlbmVzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0Lmxpc3RbW2ldXSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QubGlzdFtbaV1dLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKfQpgYGAKCiMjIyBJbnRlZ3JhdGUgb2JqZWN0cwoKYGBge3IgaW50ZWdyYXRpb259CiMjIEZpbmQgYW5jaG9ycwp0ZW54Lmp1c3R3dC5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSB0ZW54Lmp1c3R3dC5saXN0LCBkaW1zID0gMToyMSwgdmVyYm9zZSA9IEZBTFNFKQoKIyMgSW50ZWdyYXRlIGRhdGEKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IHRlbnguanVzdHd0LmFuY2hvcnMsIGRpbXMgPSAxOjIxLCB2ZXJib3NlID0gRkFMU0UsIGZlYXR1cmVzLnRvLmludGVncmF0ZSA9IGdlbmVzX2luX3RlbnhfZGF0YXNldCkKYGBgCgojIDQuIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiB7LnRhYnNldH0KCiMjIyBQQ0EKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KIyMgTWFrZSB0aGUgZGVmYXVsdCBhc3NheSBpbnRlZ3JhdGVkCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiaW50ZWdyYXRlZCIKCiMjIFJ1biB0aGUgc3RhbmRhcmQgd29ya2Zsb3cgZm9yIHZpc3VhbGl6YXRpb24gYW5kIGNsdXN0ZXJpbmcKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIFJ1blBDQSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKCiMjIGluc3BlY3QgUENzCkVsYm93UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBuZGltcyA9IDMwLCByZWR1Y3Rpb24gPSAicGNhIikKYGBgCgojIyMgT3B0aW1pc2VkIFVNQVAKQWZ0ZXIgb3B0aW1pc2F0aW9uLCB0aGUgZm9sbG93aW5nIFVNQVAgY2FuIGJlIGNhbGN1bGF0ZWQ6CmBgYHtyIHVtYXAgcnVuIDIsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA3fQojIyBSdW4gb3B0aW1pc2VkIFVNQVAKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToxMCwgbi5uZWlnaGJvcnMgPSA1MCwgc2VlZC51c2UgPSAxMjM0LCBtaW4uZGlzdCA9IDAuNCwgcmVwdWxzaW9uLnN0cmVuZ3RoID0gMC4wMywgbG9jYWwuY29ubmVjdGl2aXR5ID0gMTUwKQpgYGAKCmBgYHtyIHVtYXAgdmlzdWFsaXNlIDJ9CiMjIHBsb3QKZHAxIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBwdC5zaXplID0gMC4wNSwgZGltcyA9IGMoMSwyKSwgc3BsaXQuYnkgPSAiZXhwZXJpbWVudCIpICsgCiAgIyMgZml4IHRoZSBheGlzCiAgY29vcmRfZml4ZWQoKSAjKyAKICAjIyByZXZlcnNlIHRoZSBzY2FsZQogICNzY2FsZV95X3JldmVyc2UoKQoKIyMgdmlldwpkcDEKYGBgCgpNYWtlIGZpbmFsIHBsb3RzOgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMjIHNwbGl0IHNldXJhdCBvYmplY3QgdXAKb2IubGlzdCA8LSBTcGxpdE9iamVjdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IikKCiMjIG1ha2UgcGxvdHMgZm9yIGVhY2ggb2JqZWN0CnBsb3QubGlzdCA8LSBsYXBwbHkoWCA9IG9iLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIERpbVBsb3QoeCwgZGltcyA9IGMoMSwyKSwgcHQuc2l6ZSA9IDEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQp9KQoKY29tcG9zaXRpb25fdW1hcF8xMHggPC0gcGxvdC5saXN0JGB0ZW54XzVrYCArIAogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKHJlcGxpY2F0ZSg0NSwgIiM5OTk5OTkiKSkpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIjEweCAod2lsZC10eXBlKSIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkKCmNvbXBvc2l0aW9uX3VtYXBfc3MyIDwtIHBsb3QubGlzdCRtdXRhbnRzICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhyZXBsaWNhdGUoNDYsICIjOTk5OTk5IikpKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTbWFydC1zZXEyICh3aWxkLXR5cGUpIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKQoKY29tcG9zaXRpb25fdW1hcCA8LSBjb21wb3NpdGlvbl91bWFwXzEweCArIGNvbXBvc2l0aW9uX3VtYXBfc3MyIAoKY29tcG9zaXRpb25fdW1hcApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9jb21wb3NpdGlvbl91bWFwLnBuZyIsIHBsb3QgPSBjb21wb3NpdGlvbl91bWFwLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyfQojIyBtYWtlIHBsb3RzCiMjIGhvbyBkYXRhc2V0IGNvcnJlbGF0aW9uClVNQVBfaG9vIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuMSwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCBkaW1zID0gYygxLDIpKSArCiAgY29vcmRfZml4ZWQoKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJIb28gUHJlZGljdGVkIFRpbWVwb2ludCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBpbmZlcm5vKDEyKSkgICsKICBsYWJzKGNvbG91ciA9ICJob3VyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKIyMgYXAyZyB0aW1lY291cnNlIGluIHRoaXMgcGFwZXIgY29ycmVsYXRpb24KVU1BUF9rYXNpYSA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0LnNpemUgPSAwLjEsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIiwgZGltcyA9IGMoMSwyKSkgKwogIGNvb3JkX2ZpeGVkKCkgKyAKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyBUaW1lY291cnNlIFByZWRpY3RlZCBUaW1lcG9pbnQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gaW5mZXJubygxMCkpICArCiAgbGFicyhjb2xvdXIgPSAiaG91ciIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKCiMjIGNvbWJpbmUKdW1hcF9idWxrIDwtIHdyYXBfcGxvdHMoVU1BUF9ob28sIFVNQVBfa2FzaWEsIG5jb2wgPSAyKQoKIyMgcHJpbnQKdW1hcF9idWxrCmBgYAoKIyA1LiBDbHVzdGVyaW5nIHsudGFic2V0fSAKCiMjIyBHZW5lcmF0ZSBjbHVzdGVycwoKYGBge3J9CiMjIGdlbmVyYXRlIG5ldyBjbHVzdGVycyBhdCBsb3cgcmVzb2x1dGlvbgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmROZWlnaGJvcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IDE6MTksIHJlZHVjdGlvbiA9ICJwY2EiKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEZpbmRDbHVzdGVycyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCByZXNvbHV0aW9uID0gMiwgcmFuZG9tLnNlZWQgPSA0MiwgYWxnb3JpdGhtID0gMikKYGBgCgojIyMgdmlzdWFsaXNlIGNsdXN0ZXJzCgpgYGB7cn0KRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUsIHJlcGVsID0gRkFMU0UsIGxhYmVsID0gVFJVRSkKYGBgCgpNYWtlIGluZGl2aWR1YWwgcGxvdHMgaGlnaGxpZ2h0aW5nIHdoZXJlIGNlbGxzIGluIGVhY2ggY2x1c3RlciBmYWxsCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjIGZvciBsb29wIHdoaWNoIHRha2VzIGVhY2ggY2x1c3RlciBhbmQgbWFrZXMgYSBsaXN0IG9mIGNlbGxzIGFuZCB0aGVuIHBsb3RzIGEgaGlnaGxpZ2h0ZWQgcGxvdCBhbmQgYWRkcyBpdCB0byBhIGxpc3QKCiMjIG1ha2UgYSBibGFuayBsaXN0Cmxpc3RfVU1BUHNfYnlfY2x1c3RlciA8LSB2ZWN0b3IobW9kZSA9ICJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKQoKIyMgZm9yIGxvb3AKZm9yKGkgaW4gc2VxX2Fsb25nKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpKXsKICAjIyBtYWtlIGEgbGlzdCBvZiBjZWxscwogIGxpc3Rfb2ZfY2VsbHMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIgPT0gbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSksIF0pCiAgdW1hcF9wbG90IDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBGQUxTRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBjZWxscy5oaWdobGlnaHQgPSBsaXN0X29mX2NlbGxzLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsKICAgICMjIGZpeCBjb29yZGluYXRlcwogICAgY29vcmRfZml4ZWQoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0QzRDNEMyIsICIjMUQxNTY0IikpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJjbHVzdGVyIiwgbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yKVtpXSkpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICAjIyBhZGQgdG8gdGhlIGxpc3QKICBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbW2ldXSA8LSB1bWFwX3Bsb3QKfQoKIyMgY2hlY2sgbnVtYmVyIG9mIGNsdXN0ZXJzCmxlbmd0aChsaXN0X1VNQVBzX2J5X2NsdXN0ZXIpCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyMgdGhpcyBmdW5jdGlvbiB3cml0ZXMgdGhlIG5leHQgYml0IG9mIGNvZGUgZm9yIHlvdQojIyBwdXQgaXQgaW50byB0aGUgY29uc29sZSBhbmQgcGFzdGUgdGhlIHJlc3BvbnNlCiNwbG90eSA8LSBjKCkKI2ZvcihpIGluIHNlcV9hbG9uZyhsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzKSkpewojICBwbG90eSA8LSBwYXN0ZTAocGxvdHksICJsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWyIsIGksICJdXSIsICIgKyAiKQojfQoKIyMgcGxvdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1szXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzExXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzI0XV0KYGBgCgojIyMgRmluZCBNYXJrZXJzCgpgYGB7cn0KRGVmYXVsdEFzc2F5KHRlbnguanVzdHd0LmludGVncmF0ZWQpIDwtICJSTkEiCiMgZmluZCBtYXJrZXJzIGZvciBldmVyeSBjbHVzdGVyIGNvbXBhcmVkIHRvIGFsbCByZW1haW5pbmcgY2VsbHMsIHJlcG9ydCBvbmx5IHRoZSBwb3NpdGl2ZSBvbmVzCnBiLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgbG9nZmMudGhyZXNob2xkID0gMC4yNSkKcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSA1LCB3dCA9IGF2Z19sb2dGQykKYGBgCgpgYGB7ciwgUi5vcHRpb25zID0gbGlzdCh3aWR0aCA9IDMwMCl9Cm1hcmtlcnNfc3Vic2V0IDwtIHBiLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMjAsIHd0ID0gYXZnX2xvZ0ZDKQptYXJrZXJzX3N1YnNldF9hbm5vdGF0ZWQgPC0gbWVyZ2UobWFya2Vyc19zdWJzZXQsIGdlbmVfYW5ub3RhdGlvbnMsICBieS54ID0gImdlbmUiLCBieS55ID0gIkdlbmUuSUQiLCBhbGwgPSBGQUxTRSkKbWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkClZpZXcobWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkKQpgYGAKCiMjIyB2aXN1YWxpc2UgbWFya2VycwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIGdldCB0aGUgdG9wIDEwIGZvciBlYWNoIGNsdXN0ZXIKdG9wMTAgPC0gcGIubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nRkMpCgojIyBzY2FsZSBkYXRhIGlzIG1pc3NpbmcgLSBidXQgb3JpZ2luYWwgZGZzIGhhdmUgc2NhbGUuZGF0YQojIGRmX3NjYWxlZCA8LSBhcy5tYXRyaXgodHJhbnNmb3JtKG1lcmdlKGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMV1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QubGlzdFtbMl1dQGFzc2F5cyRSTkFAc2NhbGUuZGF0YSksIGJ5ID0gMCwgYWxsPUZBTFNFKSwgcm93Lm5hbWVzPVJvdy5uYW1lcywgUm93Lm5hbWVzPU5VTEwpKQojIHRlbnguanVzdHd0LmludGVncmF0ZWRAYXNzYXlzJFJOQUBzY2FsZS5kYXRhIDwtIGRmX3NjYWxlZAoKIyMgc2NhbGUgZGF0YSBpbiBSTkEgc2xvdAphbGwuZ2VuZXMgPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZCkKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmFycy50by5yZWdyZXNzID0gJ2V4cGVyaW1lbnQnLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKCiMjIGhlYXRtYXAKRG9IZWF0bWFwKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gdG9wMTAkZ2VuZSkgKyBOb0xlZ2VuZCgpCmBgYAoKIyA2LiBEZWZpbmUgQ2x1c3RlciBJZGVudGl0aWVzIHsudGFic2V0fSAKCiMjIyBEb3duc2FtcGxpbmcKYGBge3J9CiMgIyMgY2hlY2sgbnVtYmVyIG9mIGNlbGxzIGluIGVhY2ggY2x1c3RlcgojIGRmX2NsdXN0ZXJzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIpKQojIHBsb3QoZGZfY2x1c3RlcnMpCiMgCiMgIyMgZG93bnNhbXBsZSB1c2luZyBhcHByb3ByaWF0ZSBtZXRyaWNzCiMgdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5kb3duc2FtcGxlZCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZG93bnNhbXBsZSA9IDEwMCkKIyAgIAojICMjIGluc3BlY3QgcGxvdAojIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQuZG93bnNhbXBsZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiMgICB0aGVtZV92b2lkKCkgKyAKIyAgIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyAoQ29tbWl0bWVudCkiKSkgKyAKIyAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAojICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKYGBgCgojIyMgTWFya2VyIEdlbmVzCgp1c2VmdWwgdG9vbHMgZm9yIGFsbCBwbG90cwpgYGB7cn0KIyMgZGVmaW5lIG1hbGUgYW5kIGZlbWFsZSBzeW1ib2wKZmVtYWxlX3N5bWJvbCA8LSBpbnRUb1V0ZjgoOTc5MikKbWFsZV9zeW1ib2wgPC0gaW50VG9VdGY4KDk3OTQpCgojIyBkZWZpbmUgY29sb3VyIHBhbAptYXJrZXJfZ2VuZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiI0QzRDNEMyIsICIjMUQxNTY0IikpKDUwKQpgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIGN1dG9mZnMgLSBwdXJwbGUKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDE1fQoKbWFya2VyX2dlbmVfcGxvdF9DQ1AyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGNjcDIpfihGZW1hbGUpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTYxMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZzEpfihNYWxlKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0FQMkcgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNzUwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoYXAyZyl+KENvbW1pdG1lbnQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDgzMTAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobXNwMSl+KFNjaGl6b250KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9NU1A4IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1zcDgpfihBc2V4dWFsKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9TQlAxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTExMDEzMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoU0JQMSl+KFJpbmcpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X0ZBTUIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmYW0tYjIpfihSaW5nKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9PUkMxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA2MDIwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMob3JjMSl+KEROQX5yZXBsaWNhdGlvbikpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfQ0RQSzUgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzNTE1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhjZHBrNSl+KFNjaGl6b250KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9NQ000IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE1NjAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobWNtNCl+KEROQX5yZXBsaWNhdGlvbikpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCiMgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKIyMgcGxvdAojIyBjb3dwbG90IG1ldGhvZAptYXJrZXJfZ2VuZV9wbG90X2FsbCA8LSBwbG90X2dyaWQobWFya2VyX2dlbmVfcGxvdF9GQU1CLCBtYXJrZXJfZ2VuZV9wbG90X01TUDgsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSwgbWFya2VyX2dlbmVfcGxvdF9BUDJHLCBtYXJrZXJfZ2VuZV9wbG90X0NDUDIsIG1hcmtlcl9nZW5lX3Bsb3RfTUcxLCBtYXJrZXJfZ2VuZV9wbG90X0hTUDcwLCBucm93PTMpCgptYXJrZXJfZ2VuZV9wbG90X2FsbApgYGAKCiMjIyBNdXRhbnQgR2VuZXMKCiMjIyMgRXhwcmVzc2lvbiAtIHdpdGggY3V0b2ZmcwoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENCAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENSAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQzCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90X2ZkMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQzKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kNSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kNSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpIAogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDQgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZmQ0KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkgCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2ZkMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICMgKyBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxMzQwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDMpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2dkMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA4MjgwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoZ2QxKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKICAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfbWQxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTEzMDI3MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtZDIpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9mZDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKIyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKQojIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfZ2QxICwgbWFya2VyX2dlbmVfcGxvdF9tZDEgLCBtYXJrZXJfZ2VuZV9wbG90X21kMiAsIG1hcmtlcl9nZW5lX3Bsb3RfbWQzICwgbWFya2VyX2dlbmVfcGxvdF9tZDQgLCBtYXJrZXJfZ2VuZV9wbG90X21kNSAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQxICwgbWFya2VyX2dlbmVfcGxvdF9mZDIgLCBtYXJrZXJfZ2VuZV9wbG90X2ZkMyAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQ0LCBuY29sID0gNCkKICAgICAgICAgICAKIyMgcHJpbnQKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlCmBgYAoKc2F2ZQpgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L0FMTF9DRUxMU193dF9nZW5lX2V4cHJlc3Npb24ucG5nIiwgcGxvdCA9IG11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1ENQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0xMTQ0ODAwICAgICAgICBHQ1NLTy0yOCAgRkQ1CgoKbWFya2VyX2dlbmVfcGxvdF8xNyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDE4MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDEwMjQwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzE2NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MzUyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMTMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDkwMjMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDEzNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzMgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDgyODAwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJnZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9vb20gPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMwMjcwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8yOSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDQ3OTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzIxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NTQ4MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCiMjb3JpZ2luYWwgbGFiZWw6CiMgbGFicyh0aXRsZSA9IHBhc3RlKCIoQ0NQMjsgRmVtYWxlKSIsIlxuIiwgIlBCQU5LQV8xMzE5NTAwIikpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZSA8LSB3cmFwX3Bsb3RzKG1hcmtlcl9nZW5lX3Bsb3RfMTcgLCBtYXJrZXJfZ2VuZV9wbG90XzIgLCBtYXJrZXJfZ2VuZV9wbG90XzE5ICwgbWFya2VyX2dlbmVfcGxvdF8yMCAsIG1hcmtlcl9nZW5lX3Bsb3RfMTMgLCBtYXJrZXJfZ2VuZV9wbG90XzEwICwgbWFya2VyX2dlbmVfcGxvdF8zICwgbWFya2VyX2dlbmVfcGxvdF9vb20gLCBtYXJrZXJfZ2VuZV9wbG90XzI5ICwgbWFya2VyX2dlbmVfcGxvdF8yMSAsIG5jb2wgPSA0KQogICAgICAgICAgIAojIyBwcmludAptdXRhbnRfZXhwcmVzc2lvbl9jb21wb3NpdGUKYGBgCgoKCiMgNy4gUHNldWRvdGltZSBvbiBhbGwgY2VsbHMgey50YWJzZXR9CgojIyMgUHNldWRvdGltZSBjYWxjdWxhdGlvbgoKYGBge3J9CiMjIGV4dHJhY3QgZGF0YSBmcm9tIFNldXJhdApzZXVyYXQub2JqZWN0LmFsbCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkCiMgY291bnRzCmRhdGEgPC0gYXMoYXMubWF0cml4KEdldEFzc2F5RGF0YShzZXVyYXQub2JqZWN0LmFsbCwgYXNzYXkgPSAiaW50ZWdyYXRlZCIsIHNsb3QgPSAiZGF0YSIpKSwgJ3NwYXJzZU1hdHJpeCcpCiMgbWV0YSBkYXRhCnBkIDwtIGRhdGEuZnJhbWUoc2V1cmF0Lm9iamVjdC5hbGxAbWV0YS5kYXRhKQoKIyMga2VlcCBvbmx5IHRoZSBjb2x1bW5zIHRoYXQgYXJlIHJlbGV2YW50CiNwRGF0YSA8LSBwZCAlPiUgc2VsZWN0KG9yaWcuaWRlbnQsIG5Db3VudF9STkEsIG5GZWF0dXJlX1JOQSkKIyMgYWRkIGdlbmUgc2hvcnQgbmFtZQpmRGF0YSA8LSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvdy5uYW1lcyhkYXRhKSwgcm93Lm5hbWVzID0gcm93Lm5hbWVzKGRhdGEpKQoKIyMgQ29uc3RydWN0IG1vbm9jbGUgY2RzCm1vbm9jbGUub2JqZWN0LmFsbCA8LSBuZXdfY2VsbF9kYXRhX3NldChleHByZXNzaW9uX2RhdGEgPSBkYXRhLCBjZWxsX21ldGFkYXRhID0gcGQsIGdlbmVfbWV0YWRhdGEgPSBmRGF0YSkKIyMgcHJlcHJvY2Vzcwptb25vY2xlLm9iamVjdC5hbGwgPSBwcmVwcm9jZXNzX2Nkcyhtb25vY2xlLm9iamVjdC5hbGwsIG51bV9kaW0gPSAxMDAsIG5vcm1fbWV0aG9kID0gIm5vbmUiKQojIyBwbG90IHZhcmlhbmNlIGV4cGxhaW5lZCBwbG90CiNwbG90X3BjX3ZhcmlhbmNlX2V4cGxhaW5lZChtb25vY2xlLm9iamVjdC5hbGwpCiMjIG1ha2UgbW9ub2NsZSBVTUFQCiNtb25vY2xlLm9iamVjdC5hbGwgPSByZWR1Y2VfZGltZW5zaW9uKG1vbm9jbGUub2JqZWN0LmFsbCwgcmVkdWN0aW9uX21ldGhvZCA9ICJVTUFQIiwgcHJlcHJvY2Vzc19tZXRob2QgPSAiUENBIiwgdW1hcC5tZXRyaWMgPSAiZXVjbGlkZWFuIiwgdW1hcC5uX25laWdoYm9ycyA9IDIwLCB1bWFwLm1pbl9kaXN0ID0gMC41LCB2ZXJib3NlID0gRkFMU0UpCiNwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKCiMjIGFkZCBVTUFQIGZyb20gU2V1cmF0Cm1vbm9jbGUub2JqZWN0LmFsbEBpbnRfY29sRGF0YUBsaXN0RGF0YSRyZWR1Y2VkRGltc0BsaXN0RGF0YVtbIlVNQVAiXV0gPC1zZXVyYXQub2JqZWN0LmFsbEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MgCnBsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgY2x1c3Rlcgptb25vY2xlLm9iamVjdC5hbGwgPSBjbHVzdGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKCiMjIHBsb3QgY2x1c3RlcnMKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCBncm91cF9jZWxsc19ieT0icGFydGl0aW9uIiwgIHggPSAxLCB5ID0gMikKCiMjIHJlZHVjZSBwYXJ0aXRpb25zIHRvIDEKbW9ub2NsZS5vYmplY3QuYWxsQGNsdXN0ZXJzJFVNQVAkcGFydGl0aW9uc1ttb25vY2xlLm9iamVjdC5hbGxAY2x1c3RlcnMkVU1BUCRwYXJ0aXRpb25zID09ICIyIl0gPC0gIjEiCgojbWFwIHBzZXVkb3RpbWUKbW9ub2NsZS5vYmplY3QuYWxsID0gbGVhcm5fZ3JhcGgobW9ub2NsZS5vYmplY3QuYWxsLCBsZWFybl9ncmFwaF9jb250cm9sPWxpc3QobmNlbnRlcj01NTAsIG1pbmltYWxfYnJhbmNoX2xlbiA9IDE1KSwgdXNlX3BhcnRpdGlvbiA9IEZBTFNFKQoKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCBncm91cF9jZWxsc19ieT0icGFydGl0aW9uIiwgIHggPSAxLCB5ID0gMikKCiMjIGEgaGVscGVyIGZ1bmN0aW9uIHRvIGlkZW50aWZ5IHRoZSByb290IHByaW5jaXBhbCBwb2ludHM6CiMjIG1ha2UgY2x1c3RlciAyIHRoZSByb290CiMgZ2V0X2VhcmxpZXN0X3ByaW5jaXBhbF9ub2RlIDwtIGZ1bmN0aW9uKGNkcywgdGltZV9iaW49IjciKXsKIyAgIGNlbGxfaWRzIDwtIHdoaWNoKGNvbERhdGEoY2RzKVssICJzZXVyYXRfY2x1c3RlcnMiXSA9PSB0aW1lX2JpbikKIyAgIGNsb3Nlc3RfdmVydGV4IDwtCiMgICBjZHNAcHJpbmNpcGFsX2dyYXBoX2F1eFtbIlVNQVAiXV0kcHJfZ3JhcGhfY2VsbF9wcm9qX2Nsb3Nlc3RfdmVydGV4CiMgICBjbG9zZXN0X3ZlcnRleCA8LSBhcy5tYXRyaXgoY2xvc2VzdF92ZXJ0ZXhbY29sbmFtZXMoY2RzKSwgXSkKIyAgIHJvb3RfcHJfbm9kZXMgPC0KIyAgIGlncmFwaDo6VihwcmluY2lwYWxfZ3JhcGgoY2RzKVtbIlVNQVAiXV0pJG5hbWVbYXMubnVtZXJpYyhuYW1lcwojICAgKHdoaWNoLm1heCh0YWJsZShjbG9zZXN0X3ZlcnRleFtjZWxsX2lkcyxdKSkpKV0KIyAgIAojICAgcm9vdF9wcl9ub2RlcwojIH0KCiMjIGNhbGN1bGF0ZSBwc2V1ZG90aW1lCiNtb25vY2xlLm9iamVjdC5hbGwgPSBvcmRlcl9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIHJvb3RfcHJfbm9kZXM9Z2V0X2VhcmxpZXN0X3ByaW5jaXBhbF9ub2RlKG1vbm9jbGUub2JqZWN0LmFsbCkpCm1vbm9jbGUub2JqZWN0LmFsbCA9IG9yZGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCkKIyMgdXNlZCA1IHBvaW50cyBhdCB0aGUgYmVnaW5uaW5nCgoKIyMgcGxvdAp1bWFwX3B0IDwtIHBsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsLCBjb2xvcl9jZWxsc19ieSA9ICJwc2V1ZG90aW1lIiwgbGFiZWxfY2VsbF9ncm91cHM9RkFMU0UsIGNlbGxfc2l6ZSA9IDEsIHggPSAxLCB5ID0gMiwgbGFiZWxfYnJhbmNoX3BvaW50cz1GQUxTRSwgbGFiZWxfbGVhdmVzPUZBTFNFLCBsYWJlbF9ncm91cHNfYnlfY2x1c3Rlcj1GQUxTRSwgbGFiZWxfcm9vdHMgPSBGQUxTRSkgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9ICIiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZT0yMCksIGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dCAoc2l6ZT0yMCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTIwKSkgKyAKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMTAsIGJhcmhlaWdodCA9IDIsIHRpdGxlID0gIlBzZXVkb3RpbWUiKSkKCiMjIHZpZXcgcGxvdAp1bWFwX3B0CgojIyBoZWxwIHdhcyBvYnRhaW5lZCBmcm9tIGhlcmUKIyMgaHR0cHM6Ly9naXRodWIuY29tL3NhdGlqYWxhYi9zZXVyYXQvaXNzdWVzLzE2NTgKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvVU1BUF9wdF93dC5wbmciLCBwbG90ID0gdW1hcF9wdCwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIyMgZ2dhbmltbmF0ZSBHSUYgb2YgcHNldW9kdGltZQoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKI2luc3RhbGwucGFja2FnZXMoImdpZnNraSIpCiNpbnN0YWxsLnBhY2thZ2VzKCJhdiIpCiNsaWJyYXJ5KGdpZnNraSkKI2xpYnJhcnkoYXYpCgojIyBtYWtlIGRhdGFmcmFtZSBmb3IgcGxvdHRpbmcKIyMgZXh0cmFjdCBkYXRhIGZvciBHR3Bsb3QgdmVyc2lvbiBvZiB0aGlzCmRmX2FuaW1hdGlvbiA8LSBhcy5kYXRhLmZyYW1lKG1vbm9jbGUub2JqZWN0LmFsbEBpbnRfY29sRGF0YUBsaXN0RGF0YSRyZWR1Y2VkRGltc0BsaXN0RGF0YVtbIlVNQVAiXV0pCiMjIGFkZCBwdCB0byB0aGlzIGRhdGEgZnJhbWU6CnB0X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHBzZXVkb3RpbWUobW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiKSkKZGZfYW5pbWF0aW9uIDwtIG1lcmdlKGRmX2FuaW1hdGlvbiwgcHRfdmFsdWVzLCBieT0icm93Lm5hbWVzIikgCnJvd25hbWVzKGRmX2FuaW1hdGlvbikgPC0gZGZfYW5pbWF0aW9uJFJvdy5uYW1lcwpjb2xuYW1lcyhkZl9hbmltYXRpb24pWzRdIDwtICJwdCIKCiMjIG1ha2UgdGhlIHN0YXRpYyBwbG90CnAgPC0gZ2dwbG90KGRmX2FuaW1hdGlvbiwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG91ciA9IHB0KSkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfY29sb3VyX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIyB2aWV3IHBsb3QKcGxvdChwKQoKIyMgbWFrZSBhbmltYXRlZCBwbG90CiMjIG1ha2UgYSBjYXRlZ29yeSBmb3IgYW5pbWF0aW9uCiNkZl9hbmltYXRpb24kZ3JvdXAgPC0gY3V0KGRmX2FuaW1hdGlvbiRwdCwgMTUpCgphbmltIDwtIHAgKwogIHRyYW5zaXRpb25fdGltZShwdCkgKwogIHNoYWRvd19tYXJrKCkKCmFuaW1hdGUoYW5pbSwgaGVpZ2h0ID0gMywgd2lkdGggPSAzLCB1bml0cyA9ICJpbiIsIHJlcyA9IDE1MCwgYmcgPSAndHJhbnNwYXJlbnQnKQoKIyMgdG8gY2hhbmdlIHRoZSByZXNvbHV0aW9uIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDkwNTg1NjcvZGVmaW5lLXNpemUtZm9yLWdpZi1jcmVhdGVkLWJ5LWdnYW5pbWF0ZS1jaGFuZ2UtZGltZW5zaW9uLXJlc29sdXRpb24gCmBgYApTYXZlIGFuaW1hdGlvbgpgYGB7cn0KYW5pbV9zYXZlKCJhbmltYXRlZF9VTUFQX3RyYW5zcGFyZW50X2JnX3d0LmdpZiIsIHBhdGggPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC8iKQpgYGAKCmBgYHtyfQojIyBleHRyYWN0IHB0IHZhbHVlcwpwdF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZShwc2V1ZG90aW1lKG1vbm9jbGUub2JqZWN0LmFsbCwgcmVkdWN0aW9uX21ldGhvZCA9ICJVTUFQIikpCgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0X3ZhbHVlcywgIm9sZF9wdF92YWx1ZXMiKQpgYGAKCiMjIyMgRGVmaW5lIGNlbGwgaWRlbnRpdGllcyB3aXRoIGJyYW5jaGVzCgpEZWZpbmUgaWRlbnRpdGllcyBvZiBjZWxscyAKCm1hbGUKYGBge3J9Cm1vbm9jbGUub2JqZWN0X21hbGUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmZlbWFsZQpgYGB7cn0KbW9ub2NsZS5vYmplY3RfZmVtYWxlIDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYApiaXBvdGVudGlhbApgYGB7cn0KbW9ub2NsZS5vYmplY3RfYmlwb3QgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmFzZXh1YWwgKHByZS1icmFuY2gpCmBgYHtyfQptb25vY2xlLm9iamVjdF9hc2V4X3ByZSA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKYXNleHVhbCBmYXRlCmBgYHtyfQptb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmNoZWNrCmBgYHtyfQpkZl9mcmVxIDwtIGRhdGEuZnJhbWUodGFibGUoYyhjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X3ByZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSkpKSkKcGFzdGUoIm51bWJlciBvZiBjZWxscyBpbiBzZXVyYXQgb2JqZWN0IGlzIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0LmFsbCkpLCAiLiBUaGUgbnVtYmVyIG9mIGNlbGxzIHNlbGVjdGVkIGhlcmUgd2l0aCBhbiBpZGVudGl0aXR5IGlzIiwgZGltKGRmX2ZyZXEpWzFdKQpkZl9mcmVxIDwtIGRmX2ZyZXFbZGZfZnJlcSRGcmVxID4gMSwgXQpkZl9mcmVxCmBgYApJbnNwZWN0IHdoZXJlIHRoZXNlIG1pc3NpbmcgY2VsbHMgYXJlOgpgYGB7cn0KIyAnJW5pJScgPC0gTmVnYXRlKCclaW4lJykKIyAKIyBub3RfYXNzaWduZWRfY2VsbHMgPC0gY29sbmFtZXMobW9ub2NsZS5vYmplY3QuYWxsKVtjb2xuYW1lcyhtb25vY2xlLm9iamVjdC5hbGwpICVuaSUgYyhjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4KSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9mYXRlKSldCiMgCiMgRGltUGxvdChzZXVyYXQub2JqZWN0LCByZXBlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSA1LCBwdC5zaXplID0gMC41LCBjZWxscy5oaWdobGlnaHQgPSBub3RfYXNzaWduZWRfY2VsbHMsIGRpbXMgPSBjKDIsMSksIHJlZHVjdGlvbiA9ICJESU1fVU1BUCIpICsKIyAgIGNvb3JkX2ZpeGVkKCkgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwMDAwMCIsICIjZjU0ZTFlIikpCmBgYAoKYGBge3J9CiMjIGNyZWF0ZSBhbm5vdGF0aW9uIGRhdGFmcmFtZSBmcm9tIHRoZXNlIHJlc3VsdHM6CmRmX21vbm9jbGVfc2V4ZXMgPC0gcmJpbmQoZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X21hbGUpLCAic2V4IiA9IHJlcCgiTWFsZSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSwgInNleCIgPSByZXAoIkZlbWFsZSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9mZW1hbGUpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCksICJzZXgiID0gcmVwKCJCaXBvdGVudGlhbCIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9iaXBvdCkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfcHJlKSwgInNleCIgPSByZXAoIkFzZXh1YWxfRWFybHkiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9wcmUpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUpLCAic2V4IiA9IHJlcCgiQXNleHVhbF9MYXRlIiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSkpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAjZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IG5vdF9hc3NpZ25lZF9jZWxscywgInNleCIgPSByZXAoIlVuYXNzaWduZWQiLCBsZW5ndGgobm90X2Fzc2lnbmVkX2NlbGxzKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKZGltKGRmX21vbm9jbGVfc2V4ZXMpCgojIyBvcmRlciBsaWtlIHRoZSBtZXRhZGF0YQpkZl9tb25vY2xlX3NleGVzIDwtIGRmX21vbm9jbGVfc2V4ZXNbbWF0Y2gocm93bmFtZXMobW9ub2NsZS5vYmplY3QuYWxsQGNvbERhdGEpLCBkZl9tb25vY2xlX3NleGVzJGNlbGxfbmFtZSksIF0KCiMjIGFkZCB0aGlzIGJhY2sgaW50byB0aGUgbW9ub2NsZSBvYmplY3QKbW9ub2NsZS5vYmplY3QuYWxsQGNvbERhdGEkU2V4ZXNfbW9ub2NsZSA8LSBkZl9tb25vY2xlX3NleGVzJHNleAoKIyMgYWRkIHRoaXMgdG8gdGhlIHNldXJhdCBvYmplY3QKcm93bmFtZXMoZGZfbW9ub2NsZV9zZXhlcykgPC0gZGZfbW9ub2NsZV9zZXhlcyRjZWxsX25hbWUKZGZfbW9ub2NsZV9zZXhlc190b19hZGRfdG9fc2V1cmF0IDwtIGRmX21vbm9jbGVfc2V4ZXNbLGMoInNleCIpLCBkcm9wID0gRkFMU0VdCnRlbnguanVzdHd0LmludGVncmF0ZWQgPC0gQWRkTWV0YURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGZfbW9ub2NsZV9zZXhlc190b19hZGRfdG9fc2V1cmF0LCBjb2wubmFtZSA9ICJtb25vY2xlX3NleCIpCmBgYAoKcHQgdnMuIHJlYWwgdGltZQpgYGB7cn0KbGlicmFyeShnZ3JpZGdlcykKCmRmX3Bsb3R0aW5nIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEpCgpwdF9yZWFsX3Bsb3QgPC0gZ2dwbG90KGRmX3Bsb3R0aW5nLCBhZXMoeCA9IG9sZF9wdF92YWx1ZXMsIHkgPSAgYXMuZmFjdG9yKFByZWRpY3Rpb24uU3BlYXJtYW4uKSwgZmlsbCA9IGFzLmZhY3RvcihQcmVkaWN0aW9uLlNwZWFybWFuLikpKSArCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IC4xLAogICAgICAgICAgICAgICAgICAgICAgcmVsX21pbl9oZWlnaHQgPSAwLjAzLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWFudGlsZV9saW5lcyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVhbnRpbGVzID0gMiwKICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gMikgKyAjIHBsb3QgcmlnZGVsaW5lcyB3aXRob3V0IHBvaW50cwogICMgcGxvdCBwb2ludHMgd2l0aCBpbnZpc2libGUgcmlkZ2VsaW5lcwogIGdlb21fZGVuc2l0eV9yaWRnZXNfZ3JhZGllbnQocG9pbnRfYWxwaGEgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJlZF9wb2ludHMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHBvaW50X2NvbG9yID0gbW9ub2NsZV9zZXgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICArCiAgdGhlbWVfY2xhc3NpYygpICsKICBzY2FsZV95X2Rpc2NyZXRlKGRyb3A9RkFMU0UpICsKICBsYWJzKHRpdGxlID0gJycsIHggPSAiUHNldWRvdGltZSIsIHkgPSAiUHJlZGljdGVkIFJlYWwtdGltZSAoaHBpKSIpICsKICAjc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJwc2V1ZG90aW1lIiwgb3B0aW9uID0gIkMiLCBhbHBoYSA9IDEpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoc2l6ZSA9ICgwLjIpLCBjb2xvdXI9ImdyZXkiKQogICAgICAgICkKCnB0X3JlYWxfcGxvdApgYGAKCmBgYHtyfQpnZyA8LSBnZ3Bsb3QoZGZfcGxvdHRpbmcsIGFlcyhhcy5mYWN0b3IoUHJlZGljdGlvbi5TcGVhcm1hbi4pLCBmaWxsID0gbW9ub2NsZV9zZXgpKSArIGdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBwb3NpdGlvbj0iZmlsbCIpCgpnZwpgYGAKCgojIDguIFBsb3RzIHsudGFic2V0fQoKbWFrZSBjb21wb3NpdGUgcHNldWRvdGltZS9JRCBmaWd1cmUKCmBgYHtyfQojIDEgPSBibHVlIC0gIiMwMDUyYzUiCiMgMiA9IHJlZCAtICIjYTUyYjFlIgojIDMgPSBncmVlbiAtICIjMDE2YzAwIgojIDQgPSB5ZWxsb3cgLSAiI2ZmZTQwMCIKI3BhbF9zZXggPC0gYygiIzAwNTJjNSIsIiNmZmU0MDAiLCAiI2E1MmIxZSIsICIjMDE2YzAwIikKCiMjIGV4dHJhY3QgcHNldWRvdGltZSBudW1iZXJzIGFuZCBpZGVudGl0eSBvZiBjZWxscyB0byBhIGRhdGFmcmFtZQpkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVssYygib2xkX3B0X3ZhbHVlcyIsICJtb25vY2xlX3NleCIpXQoKIyMgaW5zcGVjdCBwb3NzaWJsZSB2YWx1ZXMKbGlzdF9vZl9zZXhlcyA8LSBuYW1lcyh0YWJsZShkZl9wdF9pZCRtb25vY2xlX3NleCkpCgojIyBtYWtlIGEgbmV3IGNvbHVtbgpkZl9wdF9pZCRjb2xvdXIgPC0gTkEKCiMjIG1ha2UgY29sb3VyIHJhbXBzCmFzZXhfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNENUUzRjUiLCAiIzAwNTJjNSIpKQptYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJ5ZWxsb3ciLCAiIzAxNmMwMCIpKQpmZW1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjYTUyYjFlIikpCmJpcG90X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjZmZlNDAwIikpCgojIyByZS1jbGFzc2lmeSB0aGUgY2VsbHMgdGhhdCBhcmUgdW5hc3NpZ25lZCBjZWxscyByZW1vdmVkIGZyb20gc2V4dWFsIGJyYW5jaCBhYm92ZToKI2RmX3B0X2lkW3doaWNoKHJvd25hbWVzKGRmX3B0X2lkKSAlaW4lIHJlbW92ZV9jZWxscyksIF0kbW9ub2NsZV9zZXggPC0gIkFzZXh1YWwiCgojIyBhc3NpZ24gdmFsdWVzIHRvIGVhY2ggY2x1c3RlcgojIyBoZWxwIGhlcmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzk5NDY2MzAvY29sb3VyLXBvaW50cy1pbi1hLXBsb3QtZGlmZmVyZW50bHktZGVwZW5kaW5nLW9uLWEtdmVjdG9yLW9mLXZhbHVlcyAKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kY29sb3VyIDwtIGFzZXhfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kY29sb3VyIDwtIG1hbGVfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpXQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kY29sb3VyIDwtIGZlbWFsZV9yYW1wKDEwMClbYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKV0KCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJCaXBvdGVudGlhbCIsIF0kY29sb3VyIDwtIGJpcG90X3JhbXAoMTAwKVthcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgojIyBjaGVjayBldmVyeXRoaW5nIGhhcyBhIHZhbHVlCiN0YWJsZShpcy5uYShkZl9wdF9pZCRjb2xvdXIpKQoKIyMgbWFrZSBpbnRvIGEgZGYKI2RmX3B0X2lkIDwtIGRmX3B0X2lkWyAsImNvbG91ciIsIGRyb3AgPSBGQUxTRV0KCiMjIGFkZCBiYWNrIHRvIHNldXJhdCBvYmplY3QKZGYgPC0gZGZfcHRfaWRbICwiY29sb3VyIiwgZHJvcCA9IEZBTFNFXQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRmLCAicHRfaWRfY29scyIpCnJtKGRmKQoKIyMgcGxvdAojIyBleHRyYWN0IFVNQVAgY29vcmRzCmRmX3VtYXBfcGxvdCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncwpkZl91bWFwX3Bsb3QgPC0gbWVyZ2UoZGZfdW1hcF9wbG90LCBkZl9wdF9pZCwgYnk9MCwgYWxsPVRSVUUpCgojIyBhZGQgdHJlZQojI1RoZSB0cmVlIGZvciBtb25vY2xlIGlzIGxvY2F0ZWQgaGVyZToKIyBtb25vY2xlLm9iamVjdEBwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRkcF9tc3QgCmljYV9zcGFjZV9kZiA8LSB0KG1vbm9jbGUub2JqZWN0LmFsbEBwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRkcF9tc3QpICU+JQogICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3RfKHByaW5fZ3JhcGhfZGltXzEgPSAiVU1BUF8xIiwgcHJpbl9ncmFwaF9kaW1fMiA9ICJVTUFQXzIiKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShzYW1wbGVfbmFtZSA9IHJvd25hbWVzKC4pLAogICAgICAgICAgICAgICAgICAgIHNhbXBsZV9zdGF0ZSA9IHJvd25hbWVzKC4pKQoKZHBfbXN0IDwtIG1vbm9jbGUub2JqZWN0LmFsbEBwcmluY2lwYWxfZ3JhcGhbWyJVTUFQIl1dCgplZGdlX2RmIDwtIGRwX21zdCAlPiUKICAgICAgaWdyYXBoOjphc19kYXRhX2ZyYW1lKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3RfKHNvdXJjZSA9ICJmcm9tIiwgdGFyZ2V0ID0gInRvIikgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oaWNhX3NwYWNlX2RmICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdF8oCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZT0ic2FtcGxlX25hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VfcHJpbl9ncmFwaF9kaW1fMT0icHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZV9wcmluX2dyYXBoX2RpbV8yPSJwcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAic291cmNlIikgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oaWNhX3NwYWNlX2RmICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdF8oCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD0ic2FtcGxlX25hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRfcHJpbl9ncmFwaF9kaW1fMT0icHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9wcmluX2dyYXBoX2RpbV8yPSJwcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAidGFyZ2V0IikKCiMjIG1ha2UgZ2dwbG90CnVtYXBfaWRfcHQgPC0gZ2dwbG90KGRmX3VtYXBfcGxvdCwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIpKSArIAogICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KGNvbCA9IGRmX3VtYXBfcGxvdCRjb2xvdXIpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGdlb21fc2VnbWVudChhZXNfc3RyaW5nKHg9InNvdXJjZV9wcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9InNvdXJjZV9wcmluX2dyYXBoX2RpbV8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhlbmQ9InRhcmdldF9wcmluX2dyYXBoX2RpbV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllbmQ9InRhcmdldF9wcmluX2dyYXBoX2RpbV8yIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1lZGdlX2RmKQoKdW1hcF9pZF9wdApgYGAKCnNhdmUKYGBge3J9CiNnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvdW1hcF9pZF9wdC5wbmciLCBwbG90ID0gdW1hcF9pZF9wdCwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKY2x1c3RlciBwbG90CmBgYHtyfQojIyMgUHJlcGFyZSBkYXRhCgojIyBleHRyYWN0IGRmIHdpdGggY2x1c3RlciBJRCwgCmRmX3B0X2lkIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyAsInNldXJhdF9jbHVzdGVycyIsIGRyb3A9RkFMU0VdCiMjIGV4dHJhY3QgVU1BUCBjb29yZHMKZGZfcGxvdCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncwpkZl9wbG90IDwtIG1lcmdlKGRmX3Bsb3QsIGRmX3B0X2lkLCBieT0wLCBhbGw9VFJVRSkKIyMgYWRkIGNvbG91ciBjb2wKZGZfcGxvdCRjb2xvdXIgPC0gZGZfcGxvdCRzZXVyYXRfY2x1c3RlcnMKbGV2ZWxzKGRmX3Bsb3QkY29sb3VyKSA8LSBsaXN0KHByaW50KGFzZXhfcmFtcCgxNylbMV0pID0gIjkiLCBhc2V4X3JhbXAoMTcpWzJdPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzNdPSIxNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbNF0gPSAiOCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbNV09ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzZdPSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs3XSA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs4XSA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs5XSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEwXSA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzExXSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEyXSA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzEzXSA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE0XSA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxNV0gPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTZdID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE3XSA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlwb3RfcmFtcCgzKVsyXSA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsZV9yYW1wKDMpWzJdID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWxlX3JhbXAoMylbM10gPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzJdID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZW1hbGVfcmFtcCg0KVszXSA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3JhbXAoNClbNF0gPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzRdID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyMgYWFiYnJldmlhdGUgY2x1c3RlcnMKZGZfcGxvdCRjbHVzdGVyX25hbWVzIDwtIGRmX3Bsb3Qkc2V1cmF0X2NsdXN0ZXJzCmxldmVscyhkZl9wbG90JGNsdXN0ZXJfbmFtZXMpIDwtIGxpc3QoQV8xPSI5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8yPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8zPSIxNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNCA9ICI4IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV81ID0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNj0gICIxNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNyA9ICIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV84ID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzkgPSAiMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMCA9ICIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzExID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTIgPSAiNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMyA9ICI3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE1ID0gIjE4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE2ID0gIjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzE3ID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCID0gIjExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzEgPSAiMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1fMiA9ICIxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8xID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzIgPSAiMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8zID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCmxpYnJhcnkoZHBseXIpCmRhdCU+JQpncm91cF9ieShjdXN0aWQpJT4lIApzdW1tYXJpc2UoTWVhbj1tZWFuKHZhbHVlKSwgTWF4PW1heCh2YWx1ZSksIE1pbj1taW4odmFsdWUpLCBNZWRpYW49bWVkaWFuKHZhbHVlKSwgU3RkPXNkKHZhbHVlKSkKCgoKIyMgcGxvdAp1bWFwX2lkIDwtIGdncGxvdChkZl9wbG90LCBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMikpICsgCiAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sID0gZGZfcGxvdCRjb2xvdXIpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKQoKdW1hcF9pZApgYGAKCmBgYHtyfQojIyB0aGVzZSBnZXQgZGVmaW5lZCBsYXRlciBvbiwgYnV0IGFyZSByZXBsaWNhdGVkIGFib3ZlIGhlcmUgZm9yIHBsb3R0aW5nCmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIG1ha2UgYSBuZXcgY29sdW1uIGZvciBwbG90dGluZwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycwoKIyMgcmVvcmRlciB0aGUgbGV2ZWxzIHNvIHlvdSBjYW4gcGxvdCB0aGUgY2x1dGVycyBhcyB5b3Ugd2lzaApteV9sZXZlbHMgPC0gYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIG1hbGVfY2x1c3RlcnMsIGZlbWFsZV9jbHVzdGVycykKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSBmYWN0b3IoeCA9IHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIGxldmVscyA9IG15X2xldmVscykKCiMjIGNoYW5nZSB0aGUgbGV2ZWxzCmxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSA8LSBsaXN0KEFfMT0iOSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMj0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMz0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzQgPSAiOCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNSA9ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzY9ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzcgPSAiMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfOCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV85ID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTAgPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEyID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTMgPSAiNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNiA9ICIyMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNyA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUCA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTV8xID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzIgPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMSA9ICIyMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8yID0gIjIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzMgPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxNyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgojIyMgQW5ub3RhdGlvbiBzZXQtdXAKCiMjIGV4dHJhY3QgcHNldWRvdGltZSBudW1iZXJzIGFuZCBpZGVudGl0eSBvZiBjZWxscyB0byBhIGRhdGFmcmFtZQpkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVssYygib2xkX3B0X3ZhbHVlcyIsICJtb25vY2xlX3NleCIsICJzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIildCgojIyBtYWtlIGEgbmV3IGNvbHVtbgpkZl9wdF9pZCRjb2xvdXIgPC0gTkEKCiMjIGFzc2lnbiBiaW5zIHRvIGVhY2ggb2YgdGhlIHZhbHVlcwojIyBoZWxwIGhlcmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzk5NDY2MzAvY29sb3VyLXBvaW50cy1pbi1hLXBsb3QtZGlmZmVyZW50bHktZGVwZW5kaW5nLW9uLWEtdmVjdG9yLW9mLXZhbHVlcyAKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCiMjIG1ha2UgY29sb3VyIHJhbXBzCmFzZXhfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNENUUzRjUiLCAiIzAwNTJjNSIpKQptYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJ5ZWxsb3ciLCAiIzAxNmMwMCIpKQpmZW1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjYTUyYjFlIikpCmJpcG90X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjZmZlNDAwIikpCgojIyBhc3NpZ24gdmFsdWVzIHRvIGVhY2ggY2x1c3RlcgojIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiY29sb3VyIl0sIGxpc3QoZGZfcHRfaWQkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyksIG1lYW4pCiMjIEJFQ0FVU0Ugd2UgaGF2ZSBvcmRlcmVkIHRoZSBjbHVzdGVycyBhbHJlYWR5LCB3ZSBjYW4gc2ltcGx5IHRha2UgdGhlIHJvdyBpbmRleCBmb3IgdGhpcyBiaXQKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvblsxOjE3LCBdJGNvbG91ciA8LSBhc2V4X3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE6MTcsIF0keF0KZGZfYW5ub3RhdGlvblsxOCwgXSRjb2xvdXIgPC0gYmlwb3RfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMTgsIF0keF0KZGZfYW5ub3RhdGlvblsxOToyMCwgXSRjb2xvdXIgPC0gbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOToyMCwgXSR4XQpkZl9hbm5vdGF0aW9uWzIxOjIzLCBdJGNvbG91ciA8LSBmZW1hbGVfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMjE6MjMsIF0keF0KCiMjIG1ha2UgY29sb3VyIHBhbGxldGUKI3BhbF9wbG90IDwtIGMoYXNleF9yYW1wKDE3MClbMSwxMSwyMSwzMSxdLCBiaXBvdF9yYW1wKDMpWzJdLCBtYWxlX3JhbXAoNSlbMzo0XSwgZmVtYWxlX3JhbXAoNSlbMjo1XSkKcGFsX3Bsb3QgPC0gYyhkZl9hbm5vdGF0aW9uJGNvbG91ciwgJyM0OUMxNkRGRicpCgojIyBwbG90CnVtYXBfd2l0aF9jbHVzdGVycyA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsCiAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBsYWJlbC5ib3ggPSBUUlVFLAogICAgICAgIGxhYmVsLnNpemUgPSA4LAogICAgICAgIGxhYmVsLmNvbG9yCT0gYyhyZXAoYygiIzAwMDAwMCIpLCAxMiksIHJlcChjKCIjZmZmZmZmIiksIDUpLCByZXAoYygiIzAwMDAwMCIpLCAyKSwiI2ZmZmZmZiIsICIjMDAwMDAwIiwgIiNmZmZmZmYiLCAiI2ZmZmZmZiIpLAogICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgcmVwZWwgPSBUUlVFLCAKICAgICAgICBsYWJlbCA9IFRSVUUsCiAgICAgICAgY29scyA9IHBhbF9wbG90KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGxhYmVscyA9IGMoIkFzZXh1YWwgMSIsICJBc2V4dWFsIDIiICwgIkFzZXh1YWwgMyIsICJBc2V4dWFsIDQiLCAiQXNleHVhbCA1IiwgIkFzZXh1YWwgNiIsICJBc2V4dWFsIDciLCAiQXNleHVhbCA4IiwgICJBc2V4dWFsIDkiLCAiQXNleHVhbCAxMCIsICJBc2V4dWFsIDExIiwgIkFzZXh1YWwgMTIiLCAiQXNleHVhbCAxMyIsICJBc2V4dWFsIDE0IiwgIkFzZXh1YWwgMTUiLCAiQXNleHVhbCAxNiIsICJBc2V4dWFsIDE3IiwgIlByb2dlbml0b3IiLCAiTWFsZSAxIiwgIk1hbGUgMiIsICJGZW1hbGUgMSIsICJGZW1hbGUgMiIsICJGZW1hbGUgMyIpLCB2YWx1ZXMgPSBwYWxfcGxvdCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkKCnVtYXBfd2l0aF9jbHVzdGVycwpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC91bWFwX3dpdGhfY2x1c3RlcnMucG5nIiwgcGxvdCA9IHVtYXBfd2l0aF9jbHVzdGVycywgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjUsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyfQojIyBleHRyYWN0IHByb3BvcnRpb24gb2YgY2VsbHMKbGlicmFyeShwbHlyKQpkZl9wcm9wX2NvbWIgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nLCB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRleHBlcmltZW50KSkKbmFtZXMoZGZfcHJvcF9jb21iKSA8LSBjKCJjbHVzdGVyIiwgImV4cGVyaW1lbnQiLCAiRnJlcSIpCgojIyBjYWxjdWFsdGUgdGhlIHBlcmNlbnRhZ2UKZGZfcHJvcF9jb21iJHBjIDwtIE5BCmRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAibXV0YW50cyIsIF0kcGMgPC0gKGRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAibXV0YW50cyIsIF0kRnJlcS9zdW0oZGZfcHJvcF9jb21iW2RmX3Byb3BfY29tYiRleHBlcmltZW50ID09ICJtdXRhbnRzIiwgXSRGcmVxKSkqMTAwCmRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAidGVueF81ayIsIF0kcGMgPC0gKGRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAidGVueF81ayIsIF0kRnJlcS9zdW0oZGZfcHJvcF9jb21iW2RmX3Byb3BfY29tYiRleHBlcmltZW50ID09ICJ0ZW54XzVrIiwgXSRGcmVxKSkqMTAwCgojIyByZW9yZGVyIGxldmVscyBpbiBWYXIxIAojZGZfcHJvcF9jb21iJGNsdXN0ZXIgPC0gZmFjdG9yKGRmX3Byb3BfY29tYiRjbHVzdGVyLCBsZXZlbHMgPSBjKCJ1bmFzc2lnbmVkIiwgIk0iLCAiRiIsICI1IiwgIjciLCAiNCIsICIzIiwgIjEiLCAiMCIsICIyIiwgIjYiKSkKCiMjIHRoZW4gcmVvcmRlciBieSB0aGlzIHNvIHRoZSBjdW1zdW0gd2lsbCB3b3JrIGJlbG93CmRmX3Byb3BfY29tYiA8LSBkZl9wcm9wX2NvbWJbcmV2KG9yZGVyKGRmX3Byb3BfY29tYiRleHBlcmltZW50LCBkZl9wcm9wX2NvbWIkY2x1c3RlcikpLF0KCiMjIENhbGN1bGF0ZSB0aGUgY3VtdWxhdGl2ZSBzdW0gb2YgbGVuIGZvciBlYWNoIGRvc2UKZGZfY3Vtc3VtIDwtIGRkcGx5KGRmX3Byb3BfY29tYiwgImV4cGVyaW1lbnQiLCB0cmFuc2Zvcm0sIGxhYmVsX3lwb3M9Y3Vtc3VtKHBjKSAtIDAuNSpwYykKaGVhZChkZl9jdW1zdW0pCiMgaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC93aWtpL2dncGxvdDItYmFycGxvdHMtcXVpY2stc3RhcnQtZ3VpZGUtci1zb2Z0d2FyZS1hbmQtZGF0YS12aXN1YWxpemF0aW9uCgojIyByZXZlcnNlIHRoZSBsZXZlbHMgaW4gVmFyMQojZGZfY3Vtc3VtJGNsdXN0ZXIgPC0gZmFjdG9yKGRmX2N1bXN1bSRjbHVzdGVyLCBsZXZlbHMgPSByZXYoYyhsZXZlbHMoZGZfY3Vtc3VtJGNsdXN0ZXIpKSkpCgoKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGdncHVicikKIyMgbWFrZSBwbG90CnBsb3RfcHJvcCA8LSBnZ3Bsb3QoZGF0YT1kZl9jdW1zdW0sIGFlcyh4PWV4cGVyaW1lbnQsIHk9cGMsIGZpbGw9Y2x1c3RlcikpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fbGFiZWxfcmVwZWwoYWVzKGxhYmVsID0gRnJlcSx5PWxhYmVsX3lwb3MsIGZpbGwgPSBmYWN0b3IoY2x1c3RlcikpLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAzLjUsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICAjZ2VvbV90ZXh0KGFlcyh5PWxhYmVsX3lwb3MsIGxhYmVsPUZyZXEpLCB2anVzdD0wLCBjb2xvcj0iYmxhY2siLCBzaXplPTMuNSkgKwogIGxhYnMoZmlsbCA9ICJDZWxsIGNsdXN0ZXIiLCB5PSAiQ2VsbCBQcm9wb3J0aW9ucyAoJSkiLCB4ID0gIlRlY2hub2xvZ3kiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobGFiZWxzID0gYygiQXNleHVhbCAxIiwgIkFzZXh1YWwgMiIgLCAiQXNleHVhbCAzIiwgIkFzZXh1YWwgNCIsICJBc2V4dWFsIDUiLCAiQXNleHVhbCA2IiwgIkFzZXh1YWwgNyIsICJBc2V4dWFsIDgiLCAgIkFzZXh1YWwgOSIsICJBc2V4dWFsIDEwIiwgIkFzZXh1YWwgMTEiLCAiQXNleHVhbCAxMiIsICJBc2V4dWFsIDEzIiwgIkFzZXh1YWwgMTQiLCAiQXNleHVhbCAxNSIsICJBc2V4dWFsIDE2IiwgIkFzZXh1YWwgMTciLCAiUHJvZ2VuaXRvciIsICJNYWxlIDEiLCAiTWFsZSAyIiwgIkZlbWFsZSAxIiwgIkZlbWFsZSAyIiwgIkZlbWFsZSAzIiksIHZhbHVlcyA9IHBhbF9wbG90KSArCiAgdGhlbWVfcHVicigpICsKICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPSByZXYoYygiMTB4IiwgIlNtYXJ0LXNlcTIiKSkpICsKICBjb29yZF9mbGlwKCkgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChuY29sPTkpKQoKcGxvdF9wcm9wCmBgYApgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L1dUX2NlbGxfdHlwZV9wcm9wb3J0aW9ucy5wbmciLCBwbG90ID0gcGxvdF9wcm9wLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gOSwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyMjIGRvdHBsb3QKCkEgZG90cGxvdCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0aGUgZXhwcmVzc2lvbiBvZiBtdWx0aXBsZSBnZW5lcyBpbiBhIGNsZWFyZXIgd2F5IHRoYW4gc3VjY2VzaXZlIFVNQVAgcGxvdHMKCmBgYHtyLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0PSA4fQojIyMgRGF0YSBzZXQtdXAKCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1EMwojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQ1IAoKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0xMzE5NTAwIC0gQ0NQMiAtIGZlbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDQxNjEwMCAtIE1HMSAtIGR5bmVuaW4gaGVhdnkgY2hhaW4gLSBtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKCm1hcmtlcl9nZW5lc19saXN0IDwtIGMoIlBCQU5LQS0xNDM3NTAwIiwgIlBCQU5LQS0xMzE5NTAwIiwgIlBCQU5LQS0wNDE2MTAwIiwgIlBCQU5LQS0wODMxMDAwIiwgIlBCQU5LQS0xMTAyMjAwIikKbXV0YW50X2dlbmVzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCiMjIHRoZXNlIGdldCBkZWZpbmVkIGxhdGVyIG9uLCBidXQgYXJlIHJlcGxpY2F0ZWQgYWJvdmUgaGVyZSBmb3IgcGxvdHRpbmcKYXNleHVhbF9lYXJseV9jbHVzdGVycyA8LSBjKDksIDQsIDE1LCA4LCAxLCAxNCwgMiwgMTAsIDMsIDAsIDYsIDUpCmFzZXh1YWxfbGF0ZV9jbHVzdGVycyA8LSBjKDcsIDEyLCAxOCwgMjAsIDIzKQpiaXBvdGVudGlvbmFsX2Vhcmx5X2NsdXN0ZXJzIDwtICMgMD8KYmlwb3RlbnRpYWxfY2x1c3RlcnMgPC0gYygxMSkgCm1hbGVfY2x1c3RlcnMgPC0gYygxNiwgMTMpCmZlbWFsZV9jbHVzdGVycyA8LSBjKDIxLCAyMiwgMTcsIDE5KQoKIyMgY29weSB0aGUgY2x1c3RlcnMgc28geW91IGRvbid0IHBlcm1hbmVudGx5IGVkaXQgdGhlIG1hc3Rlcgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycwoKIyMgcmVvcmRlciB0aGUgbGV2ZWxzIHNvIHlvdSBjYW4gcGxvdCB0aGUgY2x1dGVycyBhcyB5b3Ugd2lzaApteV9sZXZlbHMgPC0gYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIG1hbGVfY2x1c3RlcnMsIGZlbWFsZV9jbHVzdGVycykKCiMjIHJlb3JkZXIgdGhlIGxldmVscwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIGZhY3Rvcih4ID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZywgbGV2ZWxzID0gbXlfbGV2ZWxzKQoKIyMgcmVuYW1lIGNsdXN0ZXJzIHNvIHRoYXQgdGhleSBhcmUgaW50dWl0aXZlCiMgdGhpcyB0cmljayBpcyBmcm9tIGhlcmU6IGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vTWFuaXB1bGF0aW5nX2RhdGEvUmVuYW1pbmdfbGV2ZWxzX29mX2FfZmFjdG9yLwpsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZykgPC0gbGlzdChBc2V4dWFsXzE9IjkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8yPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMz0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF80ID0gIjgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF81ID0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzY9ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF83ID0gIjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF84ID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF85ID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEwID0gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzExID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEyID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEzID0gIjciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMTYgPSAiMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE3ID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQmlwb3RlbnRpYWwgPSAiMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYWxlXzEgPSAiMTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYWxlXzIgPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGVfMSA9ICIyMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZV8yID0gIjIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzMgPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGVfMyA9ICIxNyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKIyMjIEFubm90YXRpb24gc2V0LXVwCgojIyBleHRyYWN0IHBzZXVkb3RpbWUgbnVtYmVycyBhbmQgaWRlbnRpdHkgb2YgY2VsbHMgdG8gYSBkYXRhZnJhbWUKZGZfcHRfaWQgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbLGMoIm9sZF9wdF92YWx1ZXMiLCAibW9ub2NsZV9zZXgiLCAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsICJQcmVkaWN0aW9uLlNwZWFybWFuLiIsICJQcmVkaWN0aW9uLlNwZWFybWFuLl9LYXNpYSIpXQoKIyMgbWFrZSBhIG5ldyBjb2x1bW4KZGZfcHRfaWQkY29sb3VyIDwtIE5BCgojIyBhc3NpZ24gYmlucyB0byBlYWNoIG9mIHRoZSB2YWx1ZXMKIyMgaGVscCBoZXJlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy85OTQ2NjMwL2NvbG91ci1wb2ludHMtaW4tYS1wbG90LWRpZmZlcmVudGx5LWRlcGVuZGluZy1vbi1hLXZlY3Rvci1vZi12YWx1ZXMgCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgojIyBtYWtlIGNvbG91ciByYW1wcwphc2V4X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDVFM0Y1IiwgIiMwMDUyYzUiKSkKbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAieWVsbG93IiwgIiMwMTZjMDAiKSkKZmVtYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ5ZWxsb3ciLCAiI2E1MmIxZSIpKQpiaXBvdF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAiI2ZmZTQwMCIpKQoKIyMgYXNzaWduIHZhbHVlcyB0byBlYWNoIGNsdXN0ZXIKIyMgdGFrZSB0aGUgbWVhbiBvZiB0aGUgYmluCmRmX2Fubm90YXRpb24gPC0gYWdncmVnYXRlKGRmX3B0X2lkWywgImNvbG91ciJdLCBsaXN0KGRmX3B0X2lkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpLCBtZWFuKQojIyBCRUNBVVNFIHdlIGhhdmUgb3JkZXJlZCB0aGUgY2x1c3RlcnMgYWxyZWFkeSwgd2UgY2FuIHNpbXBseSB0YWtlIHRoZSByb3cgaW5kZXggZm9yIHRoaXMgYml0CmRmX2Fubm90YXRpb24kY29sb3VyIDwtIE5BCmRmX2Fubm90YXRpb25bMToxNywgXSRjb2xvdXIgPC0gYXNleF9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOjE3LCBdJHhdCmRmX2Fubm90YXRpb25bMTgsIF0kY29sb3VyIDwtIGJpcG90X3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE4LCBdJHhdCmRmX2Fubm90YXRpb25bMTk6MjAsIF0kY29sb3VyIDwtIG1hbGVfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMTk6MjAsIF0keF0KZGZfYW5ub3RhdGlvblsyMToyMywgXSRjb2xvdXIgPC0gZmVtYWxlX3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzIxOjIzLCBdJHhdCgojIyBwbG90IGFubm90YXRpb24gCiMjIHRoaXMgcmVhbGx5IGhlbHBlZDogaHR0cHM6Ly93d3cuYmlvc3RhcnMub3JnL3AvMzk2ODEwLwpoMiA8LSBnZ3Bsb3QoZGZfYW5ub3RhdGlvbikrCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLCAKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gZGZfYW5ub3RhdGlvbiRjb2xvdXIsCiAgICAgICAgICAgY29sID0gIiNGRkZGRkYiLAogICAgICAgICAgIHdpZHRoID0gMSkrCiAgICAgIHRoZW1lX3ZvaWQoKSsKICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkjKwogICAgICNmYWNldF9ncmlkKC5+Y29sb3VyLCBzY2FsZXMgPSAiZnJlZV94IikKICAgICAjbGVnZW5kIDwtIHBsb3RfZ3JpZChnZXRfbGVnZW5kKGgyKSwgZ2V0X2xlZ2VuZChoMSksIG5jb2wgPSAxKQogaDIgPC0gaDIgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAjICAgZ2VvbV9wb2ludChjb2wgPSBkZl91bWFwX3Bsb3QkY29sb3VyKQogCiBoMSA8LSBnZ3Bsb3QoZGZfYW5ub3RhdGlvbikrCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCB5ID0gMSksCiAgICAgICAgICAgIGNvbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgICBzaXplID0gNSkrCiAgICAgIHRoZW1lX3ZvaWQoKSsKICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkjKwogICAgICNmYWNldF9ncmlkKC5+Y29sb3VyLCBzY2FsZXMgPSAiZnJlZV94IikKICAgICAjbGVnZW5kIDwtIHBsb3RfZ3JpZChnZXRfbGVnZW5kKGgyKSwgZ2V0X2xlZ2VuZChoMSksIG5jb2wgPSAxKQogaDEgPC0gaDEgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAjICAgZ2VvbV9wb2ludChjb2wgPSBkZl91bWFwX3Bsb3QkY29sb3VyKQoKICMjIGFkZCBwcmVkaWN0ZWQgdGltZSBwb2ludAogIyMgdGFrZSB0aGUgbWVhbiBvZiB0aGUgYmluCmRmX2Fubm90YXRpb24gPC0gYWdncmVnYXRlKGRmX3B0X2lkWywgIlByZWRpY3Rpb24uU3BlYXJtYW4uIl0sIGxpc3QoZGZfcHRfaWQkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyksIG1lYW4pCmRmX2Fubm90YXRpb24kY29sb3VyIDwtIE5BCmRmX2Fubm90YXRpb24kY29sb3VyIDwtIHZpcmlkaXMoMzAwKVsoZGZfYW5ub3RhdGlvbiR4KSoxMF0KCmgzIDwtIGdncGxvdChkZl9hbm5vdGF0aW9uKSsKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCB5ID0gMSksIAogICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGZpbGwgPSBkZl9hbm5vdGF0aW9uJGNvbG91ciwKICAgICAgICAgICBjb2wgPSAiI0ZGRkZGRiIsCiAgICAgICAgICAgd2lkdGggPSAxKSsKICAgICAgdGhlbWVfdm9pZCgpKwogICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSMrCiAgICAgI2ZhY2V0X2dyaWQoLn5jb2xvdXIsIHNjYWxlcyA9ICJmcmVlX3giKQogICAgIGxlZ2VuZF9oMyA8LSBnZXRfbGVnZW5kKGgzKQogaDMgPC0gaDMgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgogIGgzIDwtIGdncGxvdChkYXRhID0gZGZfYW5ub3RhdGlvbiwgCiAgICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgZmlsbD14KQogICAgICAgICAgICAgICkgKwogICAgICAgZ2VvbV9iYXIoY29sID0gIiNGRkZGRkYiLCB3aWR0aCA9IDEpKwogICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpICsKICAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpcyhvcHRpb24gPSAnY2l2aWRpcycpCiBsZWdlbmRfaDMgPC0gZ2V0X2xlZ2VuZChoMykKIGgzIDwtIGgzICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogCiAjIyBhZGQga2FzaWEgZGF0YQogICMjIHRha2UgdGhlIG1lYW4gb2YgdGhlIGJpbgpkZl9hbm5vdGF0aW9uIDwtIGFnZ3JlZ2F0ZShkZl9wdF9pZFssICJQcmVkaWN0aW9uLlNwZWFybWFuLl9LYXNpYSJdLCBsaXN0KGRmX3B0X2lkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpLCBtZWFuKQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSBOQQpkZl9hbm5vdGF0aW9uJGNvbG91ciA8LSB2aXJpZGlzKDMwMClbKGRmX2Fubm90YXRpb24keCkqMTBdCgpoNCA8LSBnZ3Bsb3QoZGZfYW5ub3RhdGlvbikrCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgeSA9IDEpLCAKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gZGZfYW5ub3RhdGlvbiRjb2xvdXIsCiAgICAgICAgICAgY29sID0gIiNGRkZGRkYiLAogICAgICAgICAgIHdpZHRoID0gMSkrCiAgICAgIHRoZW1lX3ZvaWQoKSsKICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkrCiAgICAgZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgbGVnZW5kIDwtIHBsb3RfZ3JpZChnZXRfbGVnZW5kKGg0KSwgbmNvbCA9IDEpCiAgICBsZWdlbmRfaDQgPC0gZ2V0X2xlZ2VuZChoNCkKIGg0IDwtIGg0ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKIGg0IDwtIGdncGxvdChkYXRhID0gZGZfYW5ub3RhdGlvbiwgCiAgICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAuMSwgZmlsbD14KQogICAgICAgICAgICAgICkgKwogICAgICAgZ2VvbV9iYXIoY29sID0gIiNGRkZGRkYiLCB3aWR0aCA9IDEpKwogICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpICsKICAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpcygpCiBsZWdlbmRfaDQgPC0gZ2V0X2xlZ2VuZChoNCkKIGg0IDwtIGg0ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKIyMjIFBsb3QKZG90X3Bsb3RfbWFya2VycyA8LSBEb3RQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBjKG1hcmtlcl9nZW5lc19saXN0LCByZXYobXV0YW50X2dlbmVzX2xpc3QpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3QubWluID0gMC4wMDAwMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gJ1JOQScpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGNvb3JkX2ZpeGVkKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgIyBjaGFuZ2UgYXBwZWFyYW5jZSBhbmQgcmVtb3ZlIGF4aXMgZWxlbWVudHMsIGFuZCBtYWtlIHJvb20gZm9yIGFycm93cwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGFuZ2xlID0gNDUsIGhqdXN0PTEsdmp1c3Q9MSwgZmFtaWx5ID0gIkFyaWFsIiksIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhY2U9Iml0YWxpYyIpLCAKICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE2LCBmYW1pbHk9IkFyaWFsIiwgY29sb3VyPSJibGFjayIpLCAKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgCiAgICAgICAgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDEsMywxLDMpLCAibGluZXMiKSwgCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsPU5BLCBzaXplPTAuNSkpICsKICAjY2hhbmdlIHRoZSBjb2xvdXJzCiAgI3NjYWxlX2NvbG91cl92aXJpZGlzKG9wdGlvbiA9ICJpbmZlcm5vIiwgZ3VpZGUgPSAiY29sb3VyYmFyIiwgbmEudmFsdWU9IndoaXRlIiwgYmVnaW4gPSAwLCBlbmQgPSAxLCBkaXJlY3Rpb24gPSAxKSArCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGNoYW5nZSB4IGF4aXMgbGFiZWwKICAjIGxhYnMoeCA9ICJNYXJrZXIgR2VuZXMiLCB5ID0gIkNsdXN0ZXIiLCB0aXRsZSA9ICJFeHByZXNzaW9uIG9mIE1hcmtlciBHZW5lcyBieSBDbHVzdGVyIikgCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwgdGl0bGUgPSAiIikgKwogICMjIGFkZCBhcnJvd3MKICAjYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gNS41LCB4ZW5kID0gNS41LCB5ID0gMjEuNSwgeWVuZCA9IDI1LCBjb2xvdXIgPSAiZ3JlZW4iLCBzaXplPTEsIGFscGhhPTEsIGFycm93PWFycm93KGxlbmd0aD11bml0KDAuMzAsImNtIiksIHR5cGUgPSAiY2xvc2VkIikpICsKICAjYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gNS41LCB4ZW5kID0gNS41LCB5ID0gMTYuNSwgeWVuZCA9IDIxLjUsIGNvbG91ciA9ICJyZWQiLCBzaXplPTEsIGFscGhhPTEsIGFycm93PWFycm93KGxlbmd0aD11bml0KDAuMzAsImNtIiksIHR5cGUgPSAiY2xvc2VkIikpICsKICAjYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gNS41LCB4ZW5kID0gNS41LCB5ID0gMCwgeWVuZCA9IDE1LjUsIGNvbG91ciA9ICJncmV5Iiwgc2l6ZT0xLCBhbHBoYT0xLCBhcnJvdz1hcnJvdyhsZW5ndGg9dW5pdCgwLjMwLCJjbSIpLCB0eXBlID0gImNsb3NlZCIpKSArCiAgIyMgYW5ub3RhdGUgYXNleAogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAobGVuZ3RoKGMoYXNleHVhbF9lYXJseV9jbHVzdGVycywgYXNleHVhbF9sYXRlX2NsdXN0ZXJzKSkrMC41KSksIHNpemUgPSAwLjUsIGxpbmV0eXBlPSAnZGFzaGVkJykgKwogICMjIGFubm90YXRlIGJpcG90ZW50aWFsCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IChsZW5ndGgoYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLCBhc2V4dWFsX2xhdGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzKSkrMC41KSksIHNpemUgPSAwLjUsIGxpbmV0eXBlPSAnZGFzaGVkJykgKwogICMjIGFubm90YXRlIHNleGVzCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IChsZW5ndGgoYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLCBhc2V4dWFsX2xhdGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzLCBtYWxlX2NsdXN0ZXJzKSkrMC41KSksIHNpemUgPSAwLjUsIGxpbmV0eXBlPSAnZGFzaGVkJykgKwogICMjIGNoYW5nZSBsYWJlbCBvbiBib3R0b20gb2YgcGxvdCBzbyB3ZSBjYW4gaW5kaWNhdGUgbWFya2VycwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gcmV2KGMoImdkMSIsICJtZDEiLCAibWQyIiwgIm1kMyIsICJtZDQiLCAibWQ1IiwgImZkMSIsICJmZDIiLCAiZmQzIiwgImZkNCIsICJtc3A4IiwgIm1zcDEiLCAibWcxIiwgImNjcDIiLCAiYXAyZyIpKSkgKwogICMjIGNoYW5nZSBsYWJlbCBvbiBib3R0b20gb2YgcGxvdCBzbyB3ZSBjYW4gaW5kaWNhdGUgbWFya2VycwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiQXNleHVhbCAxIiwgIkFzZXh1YWwgMiIgLCAiQXNleHVhbCAzIiwgIkFzZXh1YWwgNCIsICJBc2V4dWFsIDUiLCAiQXNleHVhbCA2IiwgIkFzZXh1YWwgNyIsICJBc2V4dWFsIDgiLCAgIkFzZXh1YWwgOSIsICJBc2V4dWFsIDEwIiwgIkFzZXh1YWwgMTEiLCAiQXNleHVhbCAxMiIsICJBc2V4dWFsIDEzIiwgIkFzZXh1YWwgMTQiLCAiQXNleHVhbCAxNSIsICJBc2V4dWFsIDE2IiwgIkFzZXh1YWwgMTciLCAiUHJvZ2VuaXRvciIsICJNYWxlIDEiLCAiTWFsZSAyIiwgIkZlbWFsZSAxIiwgIkZlbWFsZSAyIiwgIkZlbWFsZSAzIikpICsKICAjIyBjaGFuZ2UgbmFtZSBvZiBsZWdlbmRzCiAgZ3VpZGVzKGNvbD1ndWlkZV9jb2xvcmJhcih0aXRsZSA9ICdTY2FsZWQgQXZlcmFnZSBFeHByZXNzaW9uJyksCiAgICAgICAgIHNpemU9Z3VpZGVfbGVnZW5kKCIlIG9mIGNlbGxzIGV4cHJlc3NpbmciKSkKCiMjIHZpZXcKI3ByaW50KGRvdF9wbG90X21hcmtlcnMpCgpwbG90IDwtIHBsb3RfZ3JpZChoNCwgaDMsIGgxLCBkb3RfcGxvdF9tYXJrZXJzLCBhbGlnbiA9ICJ2IiwgbmNvbCA9IDEsIGF4aXMgPSAidGIiLCByZWxfaGVpZ2h0cyA9IGMoMC41LCAwLjUsIDAuNSwgMTgpKSAKCmRvdF9wbG90IDwtIHBsb3RfZ3JpZChwbG90LCBsZWdlbmRfaDMsIGxlZ2VuZF9oNCwgbnJvdyA9IDEsIHJlbF93aWR0aHMgPSBjKDEwLCAxLjUsIDEuNSkpCgpkb3RfcGxvdApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9kb3RfcGxvdF9hbGwucG5nIiwgcGxvdCA9IGRvdF9wbG90LCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyOS43LCBoZWlnaHQgPSAyMSwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyA5LiBTdWJzZXQgc2V4dWFsIGNlbGxzIHsudGFic2V0fQoKTWFrZSBhIHN1YnNldHRlZCBTZXVyYXQgb2JqZWN0IG9mIHNleHVhbCBjZWxscy4gCgpJbmNsdWRlIHRoZSBwcmUtYnJhbmNoIHRvbyBhcyB3ZWxsIGFzIGFueSB3ZWlyZCBjbHVzdGVycyB0aGF0IG1heSBoYXZlIGNsdXN0ZXJlZCBvdXQuIAoKaXQncyBiZWVuIGEgd2hpbGUgc2luY2Ugd2UgbG9va2VkIGF0IHRoZSBjbHVzdGVycyBzbyBsZXQncyBjaGVjayB0aGVtIG91dCBhZ2FpbjoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIFBsb3QKRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gRkFMU0UsIHB0LnNpemUgPSAwLjA1LCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgY29vcmRfZml4ZWQoKQoKIyMgcGxvdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1szXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzExXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzI0XV0KYGBgCgojIyMgRGVmaW5lIGNlbGxzIGFuZCBzdWJzZXQKYGBge3J9CmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIGRlZmluZSBjZWxscwpjZWxsX25hbWVzX3N1YnNldF9tb25vY2xlX2lkcyA8LSByb3duYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVt0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRtb25vY2xlX3NleCAlaW4lIGMoIkFzZXh1YWxfRWFybHkiLCAiQmlwb3RlbnRpYWwiLCAiTWFsZSIsICJGZW1hbGUiKSwgXSkKCiMjIDMsIDAsIDYsIDUgYXJlIGVhcmx5IGNsdXN0ZXJzIG9mIGFzZXh1YWxzIGJlZm9yZSB0aGUgYnJhbmNoCmNlbGxfbmFtZXNfc3Vic2V0X2NsdXN0ZXJfaWRzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3RlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycyAlaW4lIGMobWFsZV9jbHVzdGVycywgZmVtYWxlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycywgMywgMCwgNiwgNSksIF0pCgpjZWxsX25hbWVzX3N1YnNldF9pbnRlcnNlY3QgPC0gaW50ZXJzZWN0KGNlbGxfbmFtZXNfc3Vic2V0X21vbm9jbGVfaWRzLCBjZWxsX25hbWVzX3N1YnNldF9jbHVzdGVyX2lkcykKCiMjIHN1YnNldCBjZWxscyBpbnRvIG5ldyBvYmplY3QKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXggPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGNlbGxzID0gY2VsbF9uYW1lc19zdWJzZXRfaW50ZXJzZWN0KQpgYGAKCiMjIyBpbnNwZWN0L2NoZWNrCmBgYHtyfQojIyBpbnNwZWN0IG9iamVjdAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleAoKIyMgbG9vayBhdCBvcmlnaW5hbCBVTUFQCkRpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IiwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArIGNvb3JkX2ZpeGVkKCkKYGBgCgojIyMgUmVtb3ZlIGNvbnRhbWluYW50IGFzZXh1YWwgY2VsbHMKCndlIHdhbnQgdG8gcmVtb3ZlOgpgYGB7cn0KIyMgbG9vayBhdCBvcmlnaW5hbCBVTUFQCnBsb3Rfc2V4dWFsX3N1YnNldHRpbmcgPC0gRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyAKICBjb29yZF9maXhlZCgpICsgCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IC0xLCBhbHBoYSA9IDUpKQoKcGxvdF9zZXh1YWxfc3Vic2V0dGluZwpgYGAKCmBgYHtyfQojIyBleHRyYWN0IGNlbGwgZW1iZWRkaW5ncwpkZl9zZXhfY2VsbF9lbWJlZGRpbmdzIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXhAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzKQoKIyMgc3Vic2V0IGFueXRoaW5nIGxvd2VyIHRoYW4gLTAuOCBpbiBVTUFQIDIgYW5kIC0wLjEgaW4gVU1BUCAxCnJlbW92ZV9jZWxscyA8LSByb3cubmFtZXMoZGZfc2V4X2NlbGxfZW1iZWRkaW5nc1t3aGljaChkZl9zZXhfY2VsbF9lbWJlZGRpbmdzJFVNQVBfMSA8IC0xKSwgXSkKCiMjIHBsb3QgdGhlc2UgY2VsbHMKRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgbGFiZWwgPSBGQUxTRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBjZWxscy5oaWdobGlnaHQgPSByZW1vdmVfY2VsbHMsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyAKICBjb29yZF9maXhlZCgpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiNmNTRlMWUiKSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImNlbGxzIGhpZ2hsaWdodGVkIHdpbGwgYmUgcmVtb3ZlZCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKIyMgRmluYWwgU3Vic2V0CmBgYHtyfQojIyBtYWtlIGtlZXAgY2VsbHMgZnJvbSB0aGUgcmVtb3ZlX2NlbGxzCiMjIG1ha2UgdGhlIG5vdCBpbiBmdW5jdGlvbgonJW5pJScgPC0gTmVnYXRlKCclaW4lJykKa2VlcF9jZWxscyA8LSBjb2xuYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleClbd2hpY2goY29sbmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgpICVuaSUgcmVtb3ZlX2NlbGxzKV0KCiMjIHN1YnNldAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGNlbGxzID0ga2VlcF9jZWxscykKCiMjIGluc3BlY3QKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgKYGBgCgpjb3B5IG9sZCBjbHVzdGVycyBvdmVyCmBgYHtyfQojIyBjb3B5IG9sZCBjbHVzdGVycwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCA8LSBBZGRNZXRhRGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXhAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycywgY29sLm5hbWUgPSAicG9zdF9pbnRlZ3JhdGlvbl9jbHVzdGVycyIpCmBgYAoKIyAxMC4gU2V4IGFzc2lnbm1lbnQgb2YgbXV0YW50cyAKCiMjIEEuIFNldXJhdCBNZXRob2QKCmBgYHtyfQojIyBmaW5kIHRyYW5zZmVyIGFuY2hvcnMKRGVmYXVsdEFzc2F5KHRlbnguanVzdHd0LmludGVncmF0ZWQpIDwtICJpbnRlZ3JhdGVkIgptZXJnZS5hbmNob3JzIDwtIEZpbmRUcmFuc2ZlckFuY2hvcnMocmVmZXJlbmNlID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcXVlcnkgPSBHQ1NLT19tdXRhbnRzLCAKICAgIGRpbXMgPSAxOjMwKQoKIyMgdHJhbnNmZXIgZGF0YSBiZXR3ZWVuIHJlZiBhbmQgcXVlcnkKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IG1lcmdlLmFuY2hvcnMsIHJlZmRhdGEgPSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIAogICAgZGltcyA9IDE6MzApCgojIyBhZGQgbWV0YSBkYXRhIHRvIG9iamVjdApHQ1NLT19tdXRhbnRzIDwtIEFkZE1ldGFEYXRhKEdDU0tPX211dGFudHMsIG1ldGFkYXRhID0gcHJlZGljdGlvbnMpCgojIyBuZXcgb2JqZWN0IGZyb20gdGhpcwptdXRhbnRfc2V1cmF0IDwtIEdDU0tPX211dGFudHMKCiMjIGxvb2sgYXQgYnJlYWtkb3duIG9mIG11dGFudCBieSBkZXNpZ25hdGlvbgpkZiA8LSBhcy5kYXRhLmZyYW1lKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhKQp0YWJsZShkZiRwcmVkaWN0ZWQuaWQsIGRmJGlkZW50aXR5X25hbWVfdXBkYXRlZCkKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGRmW2RmJGdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkcHJlZGljdGVkLmlkLCBkZl84MjAkZmx1b3Jlc2VuY2Vfc29ydGVkX29uKQpgYGAKCmluc3BlY3QgZ2QxCmBgYHtyfQpkZlt3aGljaChkZiRwcmVkaWN0ZWQuaWQgPT0gIkZlbWFsZV8xIiAmIGRmJGlkZW50aXR5X25hbWVfdXBkYXRlZCA9PSAiZ2QxIiksIF1bLCAxMTg6MTQ2XQpgYGAKCgpDYWxjdWxhdGUgc2V4IHJhdGlvcwpgYGB7cn0KIyMgdXNlIGRlc2lnbmF0aW9ucyBhYm92ZSBmb3Igc2V4ZXMKbWFsZV9jZWxscyA8LSByb3duYW1lcyhtdXRhbnRfc2V1cmF0QG1ldGEuZGF0YVttdXRhbnRfc2V1cmF0QG1ldGEuZGF0YSRwcmVkaWN0ZWQuaWQgPT0gIk1hbGUiLCBdKQpmZW1hbGVfY2VsbHMgPC0gcm93bmFtZXMobXV0YW50X3NldXJhdEBtZXRhLmRhdGFbbXV0YW50X3NldXJhdEBtZXRhLmRhdGEkcHJlZGljdGVkLmlkID09ICJGZW1hbGUiLCBdKQpzczJfbXV0YW50c19maW5hbF9tYWxlIDwtIHN1YnNldChtdXRhbnRfc2V1cmF0LCBjZWxscyA9IG1hbGVfY2VsbHMpCnNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZSA8LSBzdWJzZXQobXV0YW50X3NldXJhdCwgY2VsbHMgPSBmZW1hbGVfY2VsbHMpCgojIyBpbnNwZWN0CnNzMl9tdXRhbnRzX2ZpbmFsX21hbGUKc3MyX211dGFudHNfZmluYWxfZmVtYWxlCmBgYAoKYGBge3J9CiMjIGNhbGN1bGF0ZSBzZXggcmF0aW9zCiMjc3Vic2V0IG91dCBILCBzb3J0ZWQgY2VsbHM6CmRmX21hbGUgPC0gc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGEkZXhjbHVkZV9mb3Jfc2V4X3JhdGlvID09IEZBTFNFLF0KCmRpbShkZl9tYWxlKQoKZGZfZmVtYWxlIDwtIHNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfZmVtYWxlQG1ldGEuZGF0YSRleGNsdWRlX2Zvcl9zZXhfcmF0aW8gPT0gRkFMU0UsXQoKZGltKGRmX2ZlbWFsZSkKCiMjIG1ha2UgZGF0YWZyYW1lCmRmX3NleF9yYXRpbyA8LSBtZXJnZSgKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX21hbGUkc3ViX25hbWVfdXBkYXRlZCkpLCAKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX2ZlbWFsZSRzdWJfbmFtZV91cGRhdGVkKSksIAogIGJ5ID0gIlZhcjEiLCBhbGw9VFJVRSkKCiMgb3IgdXNlIGlkZW50aXR5X3VwZGF0ZWQKCiMjIGFkZCBuYW1lcwpuYW1lcyhkZl9zZXhfcmF0aW8pIDwtIGMoImdlbm90eXBlIiwgIm1hbGUiLCAiZmVtYWxlIikKCiMjIGNoYW5nZSB0aGUgTkFzIHRvIDAKZGZfc2V4X3JhdGlvW2lzLm5hKGRmX3NleF9yYXRpbyldIDwtIDAKCiMjIGNvbGxhcHNlIDgyMCB3aWxkLXR5cGVzIHRvZ2V0aGVyCmNvbWJpbmVkX20gPC0gZGZfc2V4X3JhdGlvW2RmX3NleF9yYXRpbyRnZW5vdHlwZSA9PSAiV1QtODIwXzNfNSIsIF0kbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kbWFsZQpjb21iaW5lZF9mIDwtIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiLCBdJGZlbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kZmVtYWxlCmRmX3NleF9yYXRpbyA8LSByYmluZChkZl9zZXhfcmF0aW8sIGMoIldULTgyMC1jb21iaW5lZCIsIGNvbWJpbmVkX20sIGNvbWJpbmVkX2YpKQojIHJlbW92ZSBvbGQgcm93cwpkZl9zZXhfcmF0aW8gPC0gZGZfc2V4X3JhdGlvWy13aGljaChkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiIHwgZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjAiKSwgXQojIG5lZWQgdG8gbWFrZSBudW1lcmljIGFnYWluCmRmX3NleF9yYXRpbyRtYWxlIDwtIGFzLm51bWVyaWMoZGZfc2V4X3JhdGlvJG1hbGUpCmRmX3NleF9yYXRpbyRmZW1hbGUgPC0gYXMubnVtZXJpYyhkZl9zZXhfcmF0aW8kZmVtYWxlKQpkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPC0gYXMuY2hhcmFjdGVyKGRmX3NleF9yYXRpbyRnZW5vdHlwZSkKIyBhZGQgbmFtZSBmb3IgV1QgY29tYmluZWQKZGZfc2V4X3JhdGlvJGdlbm90eXBlWzE3XSA8LSAiV1QtODIwLWNvbWJpbmVkIgoKIyMgY2FsY3VsYXRlIHNleCByYXRpbwpkZl9zZXhfcmF0aW8kc2V4X3JhdGlvIDwtIChkZl9zZXhfcmF0aW8kbWFsZSArIDAuMSkvKGRmX3NleF9yYXRpbyRmZW1hbGUgKyAwLjEpCgojIyBsb2cgc2V4IHJhdGlvCmRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nIDwtIGxvZzEwKGRmX3NleF9yYXRpbyRzZXhfcmF0aW8pCgojI3ZpZXcKZGZfc2V4X3JhdGlvCmBgYAoKYGBge3J9CiMjIHJlbW92ZSBXVC0yIGJlY2F1c2UgaXQgaXMgcmVhbGx5IGluYXBwcm9wcmlhdGUgdG8gaGF2ZSBhIHNleCByYXRpbyBmb3IgdGhpczoKZGZfc2V4X3JhdGlvIDwtIGRmX3NleF9yYXRpb1std2hpY2goZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC1tZDUiKSxdCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDZ9CmxpYnJhcnkobGF0ZXgyZXhwKSAjIHNvIHlvdSBjYW4gcGxvdCB0aGUgZnJhY3Rpb24sIGl0J3Mgb24gQ1JBTiBgaW5zdGFsbC5wYWNrYWdlcygibGF0ZXgyZXhwIilgCgojIyBtYWtlIGV4dHJhIGNvbHVtbiBmb3IgcGxvdHRpbmcgYWVzdGhldGljczoKZGZfc2V4X3JhdGlvJGFib3ZlIDwtIGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nID4gMAoKIyMgbWFrZSBleHRyYSBjb2x1bW4gd2l0aCByYXRpbyBpbiBpdDoKZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbiA8LSBwYXN0ZTAoZGZfc2V4X3JhdGlvJGdlbm90eXBlLCAiICgiLCBkZl9zZXhfcmF0aW8kbWFsZSwgIi8iLCBkZl9zZXhfcmF0aW8kZmVtYWxlLCAiKSIpCgojIyByZW9yZGVyIGdlbm90eXBlIHNvIGl0IGlzIGluIHRoZSBjb3JyZWN0IG9yZGVyIGZvciBwbG90dGluZwpkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uIDwtIGZhY3RvcihkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uLCBsZXZlbHMgPSBkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uW29yZGVyKGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nKV0pCgojIyBwbG90CnNleF9yYXRpb19wbG90IDwtIGdncGxvdChkZl9zZXhfcmF0aW8sIGFlcyhzZXhfcmF0aW9fbG9nLCBnZW5vdHlwZV93aXRoX24sIGNvbG9yID0gYWJvdmUpKSArCiAgICAgICMjIGFkZCB0aGUgbGluZXMgZm9yIHRoZSBsb2xsaXBvcCBwbG90CiAgICAgIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHkgPSBnZW5vdHlwZV93aXRoX24sIHhlbmQgPSBzZXhfcmF0aW9fbG9nLCB5ZW5kID0gZ2Vub3R5cGVfd2l0aF9uKSwgY29sb3IgPSAiZ3JleTUwIikgKwogICAgICAjIyBhZGQgdGhlIHBvaW50cyBmb3IgdGhlIGxvbGxpcG9wIHBsb3QKICAgICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IDQpKSArCiAgICAgICMjIGFkZCB0aGUgd2lsZC10eXBlIHJlY3RhbmdsZQogICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49IC0wLjIzMTgyNDc4LCB4bWF4ID0gMS4wMDEwNTc5NywgeW1pbj0tSW5mICwgeW1heD1JbmYsIGFscGhhPTAuNCwgY29sb3I9TkEsbGluZXR5cGUgPSAyLCBmaWxsPSIjOTk5OTk5IikgKwogICAgICAjIyBtYWtlIHByZXR0aWVyCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFtaWx5PSJBcmlhbCIpKSArIAogICAgICAjIyBjaGFuZ2UgYXhpcyBsYWJlbHMKICAgICAgbGFicyh5ID0gVGVYKCIkR2Vub3R5cGVcIFxcbGVmdChcXGZyYWN7bl97bWFsZX19e25fe2ZlbWFsZX19XFxyaWdodCkkIikpICsKICAgICAgI2xhYnMoeSA9IGV4cHJlc3Npb24ocGFzdGUoIkdlbm90eXBlIiwgZ3JvdXAoIigiLCBmcmFjKHBhc3RlKCJuIG1hbGUiKSwgIm4gZmVtYWxlIiksICIpIikpKSkgKwogICAgICB4bGFiKGV4cHJlc3Npb24ocGFzdGUoIlNleCBSYXRpbyAoIiwgbG9nWzEwXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCgiKCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhYyhwYXN0ZSgibiBtYWxlICsgMC4xIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIm4gZmVtYWxlICsgMC4xIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIpIiksICIpIiApKSkgKwogICAgICAjIyBjaGFuZ2UgY29sb3VycyBvZiBsb2xsaXBvcHMKICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjYTUyYjFlIiwgIiMwMTZjMDAiKSkgKwogICAgICAjIyBhbm5vdGF0ZSBwaGVub3R5cGVzCiAgICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSA1LjUpKSAjKwogICAgICAjZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDE0LjUpKQoKcHJpbnQoc2V4X3JhdGlvX3Bsb3QpCgojIyMgQ0hBTkdFIFRPIEJJRyBCUkFDS0VUIEhFUkU6IGh0dHBzOi8vd3d3Lm92ZXJsZWFmLmNvbS9sZWFybi9sYXRleC9CcmFja2V0c19hbmRfUGFyZW50aGVzZXMgCgojcGFzdGUoIlNleCBSYXRpbyIsICJcbiIsICJsb2cxMCgobiBtYWxlICsgMC4xKS8obiBmZW1hbGUgKyAwLjEpKSIpCiN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhbWlseT0iQXJpYWwiKSkKCiMjIGZyYWN0aW9uIHRpdGxlczogaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9mb3J1bS8jIXRvcGljL2dncGxvdDIvYmdOUm5aODJoSlkgCiMjIGh0dHBzOi8vdWMtci5naXRodWIuaW8vbG9sbGlwb3AKCiNnZ3NhdmUoZmlsZW5hbWUgPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC9zZXhfcmF0aW9fcGxvdC5wbmciLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA3LCB1bml0cyA9ICJpbiIpCmBgYAoKIyMgQi4gU0NNQVAgTWV0aG9kCgojIyMgQnVpbGQgdGhlIGluZGV4CgpgYGB7cn0KIyMjIE1ha2luZyBhbiBvcnRob2xvZyByZWZlcmVuY2UgaW5kZXgKCiMjIGxvYWQgaW4gbWNhIGRhdGEKI2NvdW50cyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfY291bnRzLmNzdiIsIHJvdy5uYW1lcyA9IDEpCiNwaGVubyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfcGhlbm8uY3N2IikKI2dncGxvdChwaGVubywgYWVzKHg9UEMyXzNkLCB5ID0gUEMzXzNkLGNvbG91cj1hYnNjbHVzdDMpKSArIGdlb21fcG9pbnQoKQoKIyMgbG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShzY21hcCkgI2h0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9zY21hcC5odG1sIApsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KSAjCgojcHJlcCB0aGUgU0NFLCBpZiB3YXMgb3JpZ2luYWxseSBhIFN1ZXJhdCBvYmplY3QgbmVlZCB0aGUgZGZzIHRvIGJlIHJlZ3VsYXIgbWF0cmljZXMKI3BiX2ZpbHRlcmVkX3NjZV9vcnRoIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoWywgY29sRGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkYWJzY2x1c3QzICE9ICI4Il0KI3NjZSA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aAojcGNhIDwtIHBsb3RQQ0Eoc2NlKQojcGNzIDwtIHBjYSRkYXRhCiN0YWJsZShyb3duYW1lcyhwY3MpPT1jb2xuYW1lcyhzY2UpKQojY29sRGF0YShzY2UpIDwtIGNiaW5kKGNvbERhdGEoc2NlKSwgcGNzKQojcm93RGF0YShzY2UpJGZlYXR1cmVfc3ltYm9sIDwtIHJvd0RhdGEoc2NlKSRnZW5lCgojIyBleHRyYWN0IGRhdGEgZnJvbSBTZXVyYXQKI2NlbGxzX3RlbnggPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkZXhwZXJpbWVudCA9PSAidGVueF81ayIpLCBdKQojdGVueC5qdXN0d3QuaW50ZWdyYXRlZC4xMGsgPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGNlbGxzID0gY2VsbHNfdGVueCkKY291bnRzID0gYXMubWF0cml4KEdldEFzc2F5RGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzbG90ID0gImNvdW50cyIsIGFzc2F5ID0gIlJOQSIpKQpwaGVubyA9IGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEpCgojIyBhZGQgVU1BUCBjb29yZGluYXRlcwpkZl9zZXhfY2VsbF9lbWJlZGRpbmdzIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MpCnBoZW5vIDwtIGNiaW5kKHBoZW5vLCBkZl9zZXhfY2VsbF9lbWJlZGRpbmdzKQoKIyMgU2V0IHVwIG9iamVjdApzY2UgPC0gU2luZ2xlQ2VsbEV4cGVyaW1lbnQobGlzdChjb3VudHM9Y291bnRzKSwKICAgIGNvbERhdGE9RGF0YUZyYW1lKGxhYmVsPXBoZW5vKSwKICAgIHJvd0RhdGE9RGF0YUZyYW1lKGZlYXR1cmVfc3ltYm9sPXJvd25hbWVzKGNvdW50cykpKQpzY2UKCiMjIG1hbnVhbCBsb2dnaW5nCiNjb3VudHNfMSA8LSBhc3NheShzY2UsICJjb3VudHMiKQojbGlic2l6ZXMgPC0gY29sU3Vtcyhjb3VudHNfMSkKI3NpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQojbG9nY291bnRzKHNjZSkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQojY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGNvdW50cyhzY2UpKQojbG9nY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGxvZ2NvdW50cyhzY2UpKQpsb2djb3VudHMoc2NlKSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpKQoKIyMgcmVtb3ZlIGZlYXR1cmVzIHdpdGggZHVwbGljYXRlZCBuYW1lcwpzY2UgPC0gc2NlWyFkdXBsaWNhdGVkKHJvd25hbWVzKHNjZSkpLCBdCgojIyBidWlsZCBzY21hcC1jZWxsIHJlZmVyZW5jZSBpbmRleCwgc2F2ZSB0aGlzIHJkcwpzY2UgPC0gc2VsZWN0RmVhdHVyZXMoc2NlLCBzdXBwcmVzc19wbG90ID0gRkFMU0UsIG5fZmVhdHVyZXMgPSAyMDAwKQp0YWJsZShyb3dEYXRhKHNjZSkkc2NtYXBfZmVhdHVyZXMpCnNldC5zZWVkKDEpCnNjZSA8LSBpbmRleENlbGwoc2NlLCBNID0gNTAsIGsgPSA4MCkKbmFtZXMobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4KQojbGVuZ3RoKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHMpCiNkaW0obWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dKQojbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dWywxOjVdCiNkaW0obWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNsdXN0ZXJzKQoKI3NhdmVSRFMocGJfZmlsdGVyZWRfc2NlX29ydGgsIGZpbGU9InBiX2ZpbHRlcmVkX3NjZV9vcnRoaW5kZXhfMjAxODExMDkucmRzIikKYGBgCgojIyMgTWFwIHRvIHRoZSBpbmRleAoKYGBge3J9CiNyb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRmZWF0dXJlX3N5bWJvbCA8LSByb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRvcnRoX25hbWUKI3Jvd25hbWVzKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSA8LSByb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRvcnRoX25hbWUKCiNwcmVwIHRoZSBTQ0UsIGlmIHdhcyBvcmlnaW5hbGx5IGEgU3VlcmF0IG9iamVjdCBuZWVkIHRoZSBkZnMgdG8gYmUgcmVndWxhciBtYXRyaWNlcwojcGJfZmlsdGVyZWRfc2NlX29ydGggPC0gcGJfZmlsdGVyZWRfc2NlX29ydGhbLCBjb2xEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRhYnNjbHVzdDMgIT0gIjgiXQojc2NlIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoCiNwY2EgPC0gcGxvdFBDQShzY2UpCiNwY3MgPC0gcGNhJGRhdGEKI3RhYmxlKHJvd25hbWVzKHBjcyk9PWNvbG5hbWVzKHNjZSkpCgojY29sRGF0YShzY2UpIDwtIGNiaW5kKGNvbERhdGEoc2NlKSwgcGNzKQoKbXV0YW50c19jb3VudHMgPSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKG11dGFudF9zZXVyYXQsIHNsb3QgPSAiY291bnRzIiwgYXNzYXkgPSAiUk5BIikpCm11dGFudHNfcGhlbm8gPSBhcy5kYXRhLmZyYW1lKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhKQoKI3Jvd0RhdGEoc2NlKSRmZWF0dXJlX3N5bWJvbCA8LSByb3dEYXRhKHNjZSkkZ2VuZQptdXRhbnRzLnNjZSA8LSBTaW5nbGVDZWxsRXhwZXJpbWVudChsaXN0KGNvdW50cz1tdXRhbnRzX2NvdW50cyksCiAgICBjb2xEYXRhPURhdGFGcmFtZShsYWJlbD1tdXRhbnRzX3BoZW5vKSwKICAgIHJvd0RhdGE9RGF0YUZyYW1lKGZlYXR1cmVfc3ltYm9sPXJvd25hbWVzKG11dGFudHNfY291bnRzKSkpCm11dGFudHMuc2NlCgojIyBhZGQgbG9nIGNvdW50cwojIyBtYW51YWwKI2NvdW50c18xIDwtIGFzc2F5KG11dGFudHMuc2NlLCAiY291bnRzIikKI2xpYnNpemVzIDwtIGNvbFN1bXMoY291bnRzXzEpCiNzaXplLmZhY3RvcnMgPC0gbGlic2l6ZXMvbWVhbihsaWJzaXplcykKI2xvZ2NvdW50cyhtdXRhbnRzLnNjZSkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQojIyBmcm9tIHNldXJhdApsb2djb3VudHMobXV0YW50cy5zY2UpIDwtIGFzLm1hdHJpeChHZXRBc3NheURhdGEobXV0YW50X3NldXJhdCwgc2xvdCA9ICJkYXRhIiwgYXNzYXkgPSAiUk5BIikpCgojUHJvamVjdCBxdWVyeSBkYXRhIHNldCBvbnRvIGNlbGwgaW5kZXgKc2NtYXBDZWxsX3Jlc3VsdHMgPC0gc2NtYXBDZWxsKAogIG11dGFudHMuc2NlLCAKICBsaXN0KHd0ID0gbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4CiAgKQopCgojI0xvb2sgaW50byB0aGUgcmVzdWx0cwojIEZvciBlYWNoIGRhdGFzZXQgdGhlcmUgYXJlIHR3byBtYXRyaWNpZXMuIGNlbGxzIG1hdHJpeCBjb250YWlucyB0aGUgdG9wIDEwIChzY21hcCBkZWZhdWx0KSBjZWxsIElEcyBvZiB0aGUgY2VsbHMgb2YgdGhlIHJlZmVyZW5jZSBkYXRhc2V0IHRoYXQgYSBnaXZlbiBjZWxsIG9mIHRoZSBwcm9qZWN0aW9uIGRhdGFzZXQgaXMgY2xvc2VzdCB0bzoKIyAgIAojICAgR2l2ZSBhc3NpZ25tZW50cyBpbiB0d28gd2F5czoKIyAgIDEuIFRha2UgdGhlIHRvcCBjZWxsIGFzc2lnbm1lbnQgYWJzIGNsdXN0LCBpZiBjb3NpbmUgc2ltaWxhcml0eSBpcyBsZXNzIHRoYW4gMC40IChvciBhZGp1c3QgaWYgbmVlZGVkKSBtYXJrIGFzIHVuYXNzaWduZWQKIyAyLiBGb3IgdGhlIHRvcCAzIG5lYXJlc3QgbmVpZ2hib3JzLCBnZXQgYSBtZWFuIG9mIHRoZSBQQ0EgY29vcmRpbmF0ZXMgYW5kIHNuYXAgdG8gdGhlIG5lYXJlc3QgY2VsbCBvZiB0aG9zZSBjb29yZGluYXRlcy4gSWYgYW55IG9mIHRoZSB0b3AgdGhyZWUgY2VsbHMgYXJlIHNpbSBiZWxvdyAwLjQgdGhlbiBtYXJrIGFzIHVuYXNzaWduZWQuCgoKIyNUb3AgY2VsbCBhc3NpZ25tZW50IG1ldGhvZAoKIyMgbG9vayBhdCBhc3NpZ25tZW50cwpzY21hcENlbGxfcmVzdWx0cyR3dCRjZWxsc1ssIDE6M10KIyMgZ2V0IGNlbGwgaW5kZXhlcyAKZ2V0Y2VsbHMgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHNbMSwgXQojIyBleGN0cmFjdCBjZWxscyBtZXRhZGF0YSBmcm9tIGluZGV4CmNkc2NlIDwtIGNvbERhdGEoc2NlKVtnZXRjZWxscywgXQojIyBleHRyYWN0IHNpbWlsYXJpdGllcwp0b3BzaW0gPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzEsIF0KIyMgZ2V0IG5hbWUgb2YgdG9wIGNlbGwgbWF0Y2hlZAptdXRhbnRzLnNjZSR0b3BjZWxsIDwtIHJvd25hbWVzKGNkc2NlKQojIyBnZXQgc2V4IGlkCm11dGFudHMuc2NlJHRvcGNlbGxfYWMgPC0gY2RzY2UkbGFiZWwubW9ub2NsZV9zZXgKIyMgZ2V0IGNvb3JkaW5hdGVzIG9mIG1hdGNoZWQgY2VsbAptdXRhbnRzLnNjZSRpbmRleFBDMSA8LSBjZHNjZSRsYWJlbC5VTUFQXzEKbXV0YW50cy5zY2UkaW5kZXhQQzIgPC0gY2RzY2UkbGFiZWwuVU1BUF8yCiNtdXRhbnRzLnNjZSRwYnB0IDwtIGNkc2NlJHBzZXVkb3RpbWUKI211dGFudHMuc2NlJHBiYnVsayA8LSBjZHNjZSRidWxrCm11dGFudHMuc2NlJHRvcGNlbGxfc3AgPC0gbXV0YW50cy5zY2UkdG9wY2VsbF9hYwptdXRhbnRzLnNjZSR0b3BzaW0gPC0gdG9wc2ltCm11dGFudHMuc2NlJHRvcGNlbGxfc3BbbXV0YW50cy5zY2UkdG9wc2ltIDwgMC40XSA8LSAidW5hc3NpZ25lZCIKdGFibGUobXV0YW50cy5zY2UkdG9wY2VsbF9zcCkKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGNvbERhdGEobXV0YW50cy5zY2UpW2NvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkdG9wY2VsbF9zcCwgZGZfODIwJGxhYmVsLmZsdW9yZXNlbmNlX3NvcnRlZF9vbikKYGBgCgpgYGB7cn0KdGFibGUoY29sRGF0YShtdXRhbnRzLnNjZSkkdG9wY2VsbF9zcCwgY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkKQpgYGAKCgpgYGB7cn0KIyMjIyBUT1AgM05OIG1ldGhvZAoKI1RoaXMgZnVuY3Rpb24gbWFrZXMgYSBsaXN0IG9mIHRoZSBQQyBtZWFucyBmb3IgZWFjaCBjZWxsIGFuZCB0aGVuIGRvLmNhbGwgYmVsb3cgcmJpbmRzIHRoZW0gaW50byBhIGRhdGFmcmFtZSBjYWxsZWQgYmlnX2RhdGEKCmRhdGFsaXN0ID0gbGlzdCgpCgpmb3IgKGkgaW4gY29sbmFtZXMoc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHMpKSB7CiAgCiAgZ2V0Y2VsbHN0ZXN0IDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JGNlbGxzWzE6MywgaV0KICBjZHNjZXRlc3QgPC0gY29sRGF0YShzY2UpW2dldGNlbGxzdGVzdCwgXQogIFBDMW1lYW4gPC0gbWVhbihjZHNjZXRlc3QkbGFiZWwuVU1BUF8xKQogIFBDMm1lYW4gPC0gbWVhbihjZHNjZXRlc3QkbGFiZWwuVU1BUF8yKQogICMgLi4uIG1ha2Ugc29tZSBkYXRhCiAgZGF0IDwtIGRhdGEuZnJhbWUoaSwgUEMxbWVhbiwgUEMybWVhbikKICBkYXQkaSA8LSBpICAjIG1heWJlIHlvdSB3YW50IHRvIGtlZXAgdHJhY2sgb2Ygd2hpY2ggaXRlcmF0aW9uIHByb2R1Y2VkIGl0PwogIGRhdGFsaXN0W1tpXV0gPC0gZGF0ICMgYWRkIGl0IHRvIHlvdXIgbGlzdAp9CgpiaWdfZGF0YSA9IGRvLmNhbGwocmJpbmQsIGRhdGFsaXN0KQojIG9yIGJpZ19kYXRhIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZGF0YWxpc3QpCiMgb3IgYmlnX2RhdGEgPC0gZGF0YS50YWJsZTo6cmJpbmRsaXN0KGRhdGFsaXN0KQoKdGVzdCA8LSBiaWdfZGF0YVsxLCBdCgpkZiA8LSBkYXRhLmZyYW1lKFg9Y29sRGF0YShzY2UpJGxhYmVsLlVNQVBfMSwgWT1jb2xEYXRhKHNjZSkkbGFiZWwuVU1BUF8yLCByb3cubmFtZXMgPSByb3duYW1lcyhjb2xEYXRhKHNjZSkpKQoKI3RoZSBzbmFwIGZ1bmN0aW9uIHNuYXBzIHRvIHRoZSBuZWFyZXN0IGNlbGwgaW4gUEMgY29vcmRpYW50ZXMKc25hcCA8LSBmdW5jdGlvbihkZiwgdGVzdCl7CiAgcmVxdWlyZShCaW9iYXNlKQogIGQgPC0gbWF0Y2hwdChhcy5tYXRyaXgoZGYpLAogICAgICAgICAgICAgICBhcy5tYXRyaXgoZGF0YS5mcmFtZShYPXRlc3QkUEMxbWVhbixZPXRlc3QkUEMybWVhbikpKQogIAogIG1pbl9yb3cgPC0gcm93bmFtZXMoZFtkJGRpc3RhbmNlPT1taW4oZCRkaXN0YW5jZSksXSkKICAKICB0ZXN0JFhfc25hcCA8LSB1bmlxdWUoZGZbbWluX3JvdywiWCJdKQogIHRlc3QkWV9zbmFwIDwtIHVuaXF1ZShkZlttaW5fcm93LCJZIl0pCiAgdGVzdCRwYl9jZWxsIDwtIG1pbl9yb3cKICAKICB0ZXN0Cn0KCiN0aGlzIGxvb3BzIHRocm91Z2ggZWFjaCBjZWxsIGFuZCBpbiBiaWdfZGF0YSBhbmQgcnVucyB0aGUgc25hcCBmdW5jdGlvbgpkYXRhbGlzdDIgPSBsaXN0KCkKY29sbmFtZXMoYmlnX2RhdGEpIDwtIGMoInNhbXBsZV9pZCIsICJQQzFtZWFuIiwgIlBDMm1lYW4iKQpmb3IgKGkgaW4gcm93bmFtZXMoYmlnX2RhdGEpKSB7CiAgdGVzdCA8LSBiaWdfZGF0YVtpLCBdCiAgY29vcmQgPC0gc25hcChkZiwgdGVzdCkKICBjb29yZCRpIDwtIGkKICBkYXRhbGlzdDJbW2ldXSA8LSBjb29yZAp9CmJpZ19kYXRhMiA9IGRvLmNhbGwocmJpbmQsIGRhdGFsaXN0MikKCgp0YWJsZShyb3duYW1lcyhiaWdfZGF0YTIpPT1yb3duYW1lcyhjb2xEYXRhKG11dGFudHMuc2NlKSkpCgphbGxwYmNkIDwtIGNvbERhdGEoc2NlKQphbGxwYmNkIDwtIGFzLmRhdGEuZnJhbWUoYWxscGJjZCkKcGJhYnNjbHVzdCA8LSBhbGxwYmNkWywgYygibGFiZWwucHRfaWRfY29scyIsICJsYWJlbC5pZGVudGl0eV9uYW1lX3VwZGF0ZWQiLCAibGFiZWwubW9ub2NsZV9zZXgiKSwgZHJvcD1GQUxTRV0KcGJhYnNjbHVzdCRwYl9zYW1wbGVfaWQgPC0gcm93bmFtZXMocGJhYnNjbHVzdCkKCiMgTm93IG1lcmdlIHRoZSBwYyBjZWxsIGFzaWdubWVudHMgd2l0aCB0aGVpciBhYnMgY2x1c3QgYW5kIGdldCBpbiB0aGUgcmlnaHQgb3JkZXIKYmlnX2RhdGEzIDwtIG1lcmdlKGJpZ19kYXRhMiwgcGJhYnNjbHVzdCwgYnkueCA9ICJwYl9jZWxsIiwgYnkueSA9ICJwYl9zYW1wbGVfaWQiLCBhbGwueD1UUlVFLCBhbGwueT1GQUxTRSkKYmlnX2RhdGE0IDwtIGJpZ19kYXRhM1ttYXRjaChyb3duYW1lcyhiaWdfZGF0YTIpLCBiaWdfZGF0YTMkc2FtcGxlX2lkKSwgXQoKCmNvbG9ycyA8LSBjKCI2Ij0iIzc4QzY3OSIsCiAgICAgICAgICAgICIyIj0iI0QxRUM5RiIsCiAgICAgICAgICAgICIwIj0iI0ZFQjI0QyIsCiAgICAgICAgICAgICIxIj0iI0Y0Q0Y2MyIsCiAgICAgICAgICAgICIzIj0iI0ZFRUVBQSIsCiAgICAgICAgICAgICI0Ij0iIzg1QjFEMyIsCiAgICAgICAgICAgICI3Ij0iIzllY2FlMSIsCiAgICAgICAgICAgICI1Ij0iI0M5RThGMSIsCiAgICAgICAgICAgICJNIj0gIiNCN0I3RDgiLAogICAgICAgICAgICAiRiI9IiM5Qzk2QzYiLAogICAgICAgICAgICAidW5hc3NpZ25lZCI9ImJsYWNrIikKCmdncGxvdChiaWdfZGF0YTQsIGFlcyhQQzFtZWFuLCBQQzJtZWFuKSkgKwogIGdlb21fcG9pbnQoY29sID0gYmlnX2RhdGE0JGxhYmVsLnB0X2lkX2NvbHMpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKQoKIysgZ2VvbV9wb2ludChhZXMoY29sb3VyPWZhY3RvcihiaWdfZGF0YTQkbGFiZWwubGFiZWwucHRfaWRfY29scykpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpIAoKICAgICAgICAgICAgICAgICAgICAgCgpnZ3Bsb3QoYmlnX2RhdGE0LCBhZXMoWF9zbmFwLCBZX3NuYXApKSArCiAgZ2VvbV9wb2ludChjb2wgPSBiaWdfZGF0YTQkbGFiZWwucHRfaWRfY29scykgKwogICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpIAoKIysgZ2VvbV9wb2ludChhZXMoY29sb3VyPWZhY3RvcihiaWdfZGF0YTQkbGFiZWwubGFiZWwucHRfaWRfY29scykpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpIAoKIyNhZGQgaW5mbyB0byBTQ0UgYW5kIHNhdmUgY29sRGF0YSwgdG8gYmUgYW4gYXNzaWduZWQgY2VsbCBhbGwgM05OIG11c3QgaGF2ZSBhIGNvcyBzaW0gPjAuNApzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbLCAxOjNdCnRvcHNpbTEgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzEsIF0KdG9wc2ltMiA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbMiwgXQp0b3BzaW0zIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1szLCBdCgp0YWJsZShiaWdfZGF0YTQkc2FtcGxlX2lkPT1yb3duYW1lcyhjb2xEYXRhKG11dGFudHMuc2NlKSkpCiNwZm9iaiRwYl9jZWxsIDwtIGJpZ19kYXRhNCRwYl9jZWxsCiNwZm9iaiRQQzFtZWFuIDwtIGJpZ19kYXRhNCRQQzFtZWFuCmJkNCA8LSBiaWdfZGF0YTRbLCBjKCJwYl9jZWxsIiwgInNhbXBsZV9pZCIsICJQQzFtZWFuIiwgIlBDMm1lYW4iLCAiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5wdF9pZF9jb2xzIiwgImxhYmVsLmlkZW50aXR5X25hbWVfdXBkYXRlZCIsICJsYWJlbC5tb25vY2xlX3NleCIpXQoKY29sRGF0YShtdXRhbnRzLnNjZSkgPC0gY2JpbmQoY29sRGF0YShtdXRhbnRzLnNjZSksIGJkNCkKCm11dGFudHMuc2NlJHRvcHNpbTEgPC0gdG9wc2ltMQptdXRhbnRzLnNjZSR0b3BzaW0yIDwtIHRvcHNpbTIKbXV0YW50cy5zY2UkdG9wc2ltMyA8LSB0b3BzaW0zCm11dGFudHMuc2NlJHN0YWdlX3ByZWQgPC0gYmlnX2RhdGE0JGxhYmVsLm1vbm9jbGVfc2V4Cm11dGFudHMuc2NlJHN0YWdlX3ByZWRbbXV0YW50cy5zY2UkdG9wc2ltMSA8IDAuNCB8IG11dGFudHMuc2NlJHRvcHNpbTIgPCAwLjQgfCBtdXRhbnRzLnNjZSR0b3BzaW0zIDwgMC40XSA8LSAidW5hc3NpZ25lZCIKdGFibGUobXV0YW50cy5zY2Ukc3RhZ2VfcHJlZCkKCiN3cml0ZS5jc3YoYmQ0LCAicGZjZWxsYXNzaWdubWVudHN3aXRobWVhbjNubl8yMDE4MTAyOS5jc3YiKQojd3JpdGUuY3N2KGNvbERhdGEocGZvYmopLCAicGYzZDcxMDBzY21hcGNsdXN0czJtZXRob2RpbmRleG4xMDBfMjAxOTAxMDcuY3N2IikKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGNvbERhdGEobXV0YW50cy5zY2UpW2NvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkc3RhZ2VfcHJlZCwgZGZfODIwJGxhYmVsLmZsdW9yZXNlbmNlX3NvcnRlZF9vbikKYGBgCgpgYGB7cn0KdGFibGUoY29sRGF0YShtdXRhbnRzLnNjZSkkc3RhZ2VfcHJlZCwgY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkKQpgYGAKCgojIyBtYWtlIGZpbmFsIHBsb3Qgd2l0aCBNQ0EgZGF0YSBiZWxvdwpgYGB7cn0KIyMgUmVhZCBpbiBNQ0EgZGF0YQpwaGVubyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfcGhlbm8uY3N2IikKIyMgZXh0cmFjdCByb3dzIG5lZWRlZCBmb3IgcGxvdHRpbmcKZGZfcGxvdCA8LSBwaGVub1ssYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiKV0KZGZfcGxvdCRleHBlcmltZW50IDwtIGRmX3Bsb3QkYWJzY2x1c3QzCgojIyBleHRyYWN0IHJvd3MgbmVlZGVkIGZvciBwbG90dGluZyBmcm9tIG1hcHBlZCBvYmplY3QKZGZfcGxvdF9wbSA8LSBhcy5kYXRhLmZyYW1lKGNvbERhdGEocG1fc3MyX2ZpZWxkLnNjZS5vcnRoKSkKZGZfcGxvdF9wbSA8LSBkZl9wbG90X3BtWyAsYygiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5hYnNjbHVzdDMiKV0KZGZfcGxvdF9wbSRleHBlcmltZW50IDwtICJwbSIKY29sbmFtZXMoZGZfcGxvdF9wbSkgPC0gYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiLCAiZXhwZXJpbWVudCIpCgojIyBleHRyYWN0IHJvd3MgbmVlZGVkIGZvciBwbG90dGluZyBmcm9tIG1hcHBlZCBvYmplY3QKZGZfcGxvdF9wZiA8LSBhcy5kYXRhLmZyYW1lKGNvbERhdGEocGZfc3MyX2ZpZWxkLnNjZS5vcnRoKSkKZGZfcGxvdF9wZiA8LSBkZl9wbG90X3BmWyAsYygiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5hYnNjbHVzdDMiKV0KZGZfcGxvdF9wZiRleHBlcmltZW50IDwtICJwZiIKY29sbmFtZXMoZGZfcGxvdF9wZikgPC0gYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiLCAiZXhwZXJpbWVudCIpCgojIyBiaW5kIHRvZ2V0aGVyCmRmX3Bsb3QgPC0gcmJpbmQoZGZfcGxvdCwgZGZfcGxvdF9wZiwgZGZfcGxvdF9wbSkKCmNvbG9ycyA8LSBjKCI2Ij0iIzc4QzY3OSIsCiAgICAgICAgICAgICIyIj0iI0QxRUM5RiIsCiAgICAgICAgICAgICIwIj0iI0ZFQjI0QyIsCiAgICAgICAgICAgICIxIj0iI0Y0Q0Y2MyIsCiAgICAgICAgICAgICIzIj0iI0ZFRUVBQSIsCiAgICAgICAgICAgICI0Ij0iIzg1QjFEMyIsCiAgICAgICAgICAgICI3Ij0iIzllY2FlMSIsCiAgICAgICAgICAgICI1Ij0iI0M5RThGMSIsCiAgICAgICAgICAgICJNIj0gIiNCN0I3RDgiLAogICAgICAgICAgICAiRiI9IiM5Qzk2QzYiLAogICAgICAgICAgICAidW5hc3NpZ25lZCI9ImJsYWNrIiwKICAgICAgICAgICAgInBtIiA9ICIjZGM2NWE0IiwKICAgICAgICAgICAgInBmIiA9ICIjMjQyNDVmIikKCiMjIGFkZCBhbHBoYSBmb3IgcGxvdHRpbmcKZGZfcGxvdCRhbHBoYVshZGZfcGxvdCRleHBlcmltZW50ID09ICJwbSJdIDwtIDAuNQpkZl9wbG90JGFscGhhW2RmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iXSA8LSAxCmRmX3Bsb3QkYWxwaGFbZGZfcGxvdCRleHBlcmltZW50ID09ICJwZiJdIDwtIDEKCiMjcGxvdApzY21hcF9wY2EgPC0gZ2dwbG90KGRmX3Bsb3QsIGFlcyh4PVBDMl8zZCwgeSA9IFBDM18zZCxjb2xvdXI9ZXhwZXJpbWVudCwgYWxwaGEgPSBhbHBoYSkpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpICsKICAjIyByZW1vdmUgYWxwaGEgc2NhbGUKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKGd1aWRlPUZBTFNFKQogICMjIGRyYXcgcmluZyBhcm91bmQgZmllbGQgc2FtcGxlcwogICNnZW9tX3BvaW50KGRhdGE9ZGZfcGxvdFtkZl9wbG90JGV4cGVyaW1lbnQgPT0gInBtIiwgXSwgcGNoPTIxLCBmaWxsPU5BLCBzaXplPTIsIGNvbG91cj0iYmxhY2siLCBzdHJva2U9MSkgKwogICMjIG1ha2Ugbm9uLWZpZWxkIHNhbXBsZXMgbW9yZSBvcGFxdWUKICAjZ2VvbV9wb2ludChkYXRhPWRmX3Bsb3RbLWRmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iLCBdLCBhbHBoYSA9IDAuMikKCiMjIHZpZXcKc2NtYXBfcGNhXzIgPC0gc2NtYXBfcGNhICsgCiAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTQpKSkKCnNjbWFwX3BjYV8yCmBgYAoKc2F2ZQpgYGB7cn0KI2dnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9maWVsZF9zYW1wbGVzX3NjbWFwLnBuZyIsIHBsb3QgPSBzY21hcF9wY2FfMiwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMTUsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIyBPdmVybGFwIGFuZCB2YWxpZGF0aW9uCgpgYGB7cn0KCmBgYAoKYGBge3J9CgpgYGAKCiMgMTEuIFNhdmUgYW5kIEV4cG9ydCB7LnRhYnNldH0KCiMjIHNhdmUKClNhdmUgZW52aXJvbm1lbnQKYGBge3J9CiMjIFRoaXMgc2F2ZXMgZXZlcnl0aGluZyBpbiB0aGUgZ2xvYmFsIGVudmlyb25tZW50IGZvciBlYXN5IHJlY2FsbCBsYXRlcgojc2F2ZS5pbWFnZShmaWxlID0gIkdDU0tPX21lcmdlLlJEYXRhIikKI2xvYWQoZmlsZSA9ICJHQ1NLT19tZXJnZS5SRGF0YSIpCmBgYAoKU2F2ZSBvYmplY3QocykKYGBge3J9CiMjIFNhdmUgYW4gb2JqZWN0IHRvIGEgZmlsZQpzYXZlUkRTKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LlJEUyIpCiMjIFJlc3RvcmUgdGhlIG9iamVjdAojcmVhZFJEUyhmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbngubXV0YW50LmludGVncmF0ZWQuc2V4LlJEUyIpCgojIyBzYXZlIGludGVncmF0ZWQgb2JqZWN0IHRvIGZpbGUKc2F2ZVJEUyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuUkRTIikgCiMjIHJlc3RvcmUgdGhlIG9iamVjdAojdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLlJEUyIpCgojIyBzYXZlIG1vbm9jbGUgb2JqZWN0CnNhdmVSRFMobW9ub2NsZS5vYmplY3QuYWxsLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L21vbm9jbGUub2JqZWN0LmFsbC5SRFMiKSAKIyMgcmVzdG9yZSB0aGUgb2JqZWN0CiNtb25vY2xlLm9iamVjdC5hbGwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvbW9ub2NsZS5vYmplY3QuYWxsLlJEUyIpCgojIyBzYXZlIGludGVncmF0ZWQgb2JqZWN0IHRvIGZpbGUKI3NhdmVSRFMoR0NTS09fbXV0YW50cywgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC9HQ1NLT19tdXRhbnRzLlJEUyIpIAojIyByZXN0b3JlIHRoZSBvYmplY3QKI3RlbnguanVzdHd0LmludGVncmF0ZWQgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5SRFMiKQoKIyMgZXh0cmFjdCBVTUFQIGNvb3JkaW5hdGVzIGFuZCBtZXRhZGF0YQojIyBleHRyYWN0IG1ldGFkYXRhCm1jYV93ZWJzaXRlX2RmIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhCgojIyBhZGQgdW1hcCAtIG1lcmdlIG9uIHJvdyBuYW1lcyBhbmQgdGhlbiBtYWtlIHN1cmUgcm93IG5hbWVzIGFyZSBub3QgZHJvcHBlZCBvciBhZGRlZAptY2Ffd2Vic2l0ZV9kZiA8LSB0cmFuc2Zvcm0obWVyZ2UobWNhX3dlYnNpdGVfZGYsIHRlbnguanVzdHd0LmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzLCBieT0wLCBhbGw9VFJVRSksIHJvdy5uYW1lcz1Sb3cubmFtZXMsIFJvdy5uYW1lcz1OVUxMKQoKIyMgc2VuZCB0aGlzIHRvIHN1bmlsOgojIGdncGxvdChtY2Ffd2Vic2l0ZV9kZiwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIpKSArCiMgZ2VvbV9wb2ludChjb2wgPSBtY2Ffd2Vic2l0ZV9kZiRwdF9pZF9jb2xzKSArCiMgdGhlbWVfdm9pZCgpICsKIyBjb29yZF9maXhlZCgpCgojIyBleHBvcnQKd3JpdGUuY3N2KG1jYV93ZWJzaXRlX2RmLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L21jYV93ZWJzaXRlX2RmLmNzdiIpCmBgYAoKQ2xlYW4gdXAKYGBge3J9CiNybShzczJfd3RfY2VsbHMpCiNybSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKQojcm0odGVueC5qdXN0d3QubGlzdCkKYGBgCgojIyBmaW5hbCBmaWd1cmUgY29uc3RydWN0aW9uCgpbQ293cGxvdF0oaHR0cHM6Ly93aWxrZWxhYi5vcmcvY293cGxvdC9hcnRpY2xlcy9wbG90X2dyaWQuaHRtbCkocGxvdF9ncmlkKSwgW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay92aWduZXR0ZXMvcGF0Y2h3b3JrLmh0bWwpKHdyYXBfcGxvdHMpLCBhbmQgW2dncHVicl0oaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC9hcnRpY2xlcy8yNC1nZ3B1YnItcHVibGljYXRpb24tcmVhZHktcGxvdHMvODEtZ2dwbG90Mi1lYXN5LXdheS10by1taXgtbXVsdGlwbGUtZ3JhcGhzLW9uLXRoZS1zYW1lLXBhZ2UvKSBjYW4gYWxsIGFsbG93IG11bHRpcGxlIHBsb3RzIHRvIGJlIHBsb3R0ZWQgdG9nZXRoZXIuIAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CiMjIEEKIyB1bWFwX2lkX3B0CiMjIEIKIyBtYXJrZXIgZ2VuZSBleHByZXNzaW9uCiMjIEMKIyBNdXRhbnQgZ2VuZSBleHByZXNzaW9uCiMjIEQKIyBNb2R1bGVzCgojRmlndXJlX0EgPC0gZ3JpZC5hcnJhbmdlKGFycmFuZ2VHcm9iKFFDX2NvbXBvc2l0ZV9wbG90LCBRQ19taXRvX3Zpb2xpbiwgUUNfbWl0b19ncmFwaCwgUUNfYnlfZ2Vub3R5cGUsIG1hcHBpbmdfcmF0ZV9wbG90KSwgbnJvdz0zKSwgbnJvdz0yLCBoZWlnaHRzPWMoMTAsMikpCgojIyBjb3dwbG90IG1ldGhvZAojIyBjYW4gdXNlIHRoaXMgZm9yIGxhYmVsczogdG91cHBlcihsZXR0ZXJzKVsxOjEwXQoKIyMgQy4gTXV0YW50IGdlbmVzCm11dGFudF9nZW5lc19maWd1cmUgPC0gcGxvdF9ncmlkKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyBtYXJrZXIgZ2VuZXMgc3RhcnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9NU1A4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01TUDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01HMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZ2QxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9tZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9mZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZmQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkNCwgCiAgbGFiZWxfc2l6ZSA9IDEsIAogIG5yb3cgPSA0KQoKIyMgbGFiZWxzIGFzIHVwcGVyY2FzZSBsZXR0ZXJzOgojYyh0b3VwcGVyKGxldHRlcnMpWzI6MTddKQojIGxhYmVscyBhcyByb21hbiBudW1lcmFsczoKIyBjKHRvbG93ZXIoYXMucm9tYW4oYygyOjE3KSkKCkZpZ3VyZV9wdWJsaWNhdGlvbiA8LSBwbG90X2dyaWQodW1hcF9pZF9wdCArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGFudF9nZW5lc19maWd1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIGVtcHR5IHBsb3QgdG8gZ2l2ZSBzcGFjaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyB0aGVtZV92b2lkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygnQScsICdCJyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3NpemUgPSAxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDEsIDEsIDQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLCAyLCAzKSkKCkZpZ3VyZV9wdWJsaWNhdGlvbgpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9GaWd1cmVfQy5wbmciLCBwbG90ID0gRmlndXJlX3B1YmxpY2F0aW9uLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CmxheW91dCA8LSAiCkFBQUJCQgpDQ0RERUUKRkZHR0hICklJSkpLSwoiCgpGaWd1cmVfcHVibGljYXRpb25fQSA8LSAoY29tcG9zaXRpb25fdW1hcF8xMHggKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkpICsKKGNvbXBvc2l0aW9uX3VtYXBfc3MyICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpKSArIApwbG90X2xheW91dChuY29sID0gMikKCkZpZ3VyZV9wdWJsaWNhdGlvbiA8LSBGaWd1cmVfcHVibGljYXRpb25fQSArCiMoVU1BUF9ob28gKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgQXNleHVhbCBDeWNsZSBSZWFsIFRpbWVwb2ludCIpKSArCiMoVU1BUF9rYXNpYSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMTApKSArIGxhYnModGl0bGU9IlByZWRpY3RlZCBHYW1ldG9jeXRvZ2VuZXNpcyBSZWFsIFRpbWVwb2ludCIpKSArCiAgIyMgbWFya2VyIGdlbmVzCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiArCm1hcmtlcl9nZW5lX3Bsb3RfTVNQOCArCm1hcmtlcl9nZW5lX3Bsb3RfTVNQMSArCm1hcmtlcl9nZW5lX3Bsb3RfQ0RQSzUgKwptYXJrZXJfZ2VuZV9wbG90X0FQMkcgKwptYXJrZXJfZ2VuZV9wbG90X0NDUDIgKwptYXJrZXJfZ2VuZV9wbG90X01HMSArCm1hcmtlcl9nZW5lX3Bsb3RfT1JDMSArCm1hcmtlcl9nZW5lX3Bsb3RfTUNNNCArCiAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCiNtYXJrZXJfZ2VuZV9wbG90X2dkMSArCiNtYXJrZXJfZ2VuZV9wbG90X21kMSArCiNtYXJrZXJfZ2VuZV9wbG90X21kMiArCiNtYXJrZXJfZ2VuZV9wbG90X21kMyArCiNtYXJrZXJfZ2VuZV9wbG90X21kNCArIAojbWFya2VyX2dlbmVfcGxvdF9tZDUgKwojbWFya2VyX2dlbmVfcGxvdF9mZDEgKwojbWFya2VyX2dlbmVfcGxvdF9mZDIgKwojbWFya2VyX2dlbmVfcGxvdF9mZDMgKwojbWFya2VyX2dlbmVfcGxvdF9mZDQgKyAKcGxvdF9sYXlvdXQobmNvbCA9IDYsIAogICAgICAgICAgICB3aWR0aHMgPSBjKDEsIDEsIDEsIDEsIDEgLDEpLAogICAgICAgICAgICBoZWlnaHRzID0gYygyLCAxLCAxLCAxKSwKICAgICAgICAgICAgZGVzaWduID0gbGF5b3V0CiAgICAgICAgICAgICkKCkZpZ3VyZV9wdWJsaWNhdGlvbgpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9GaWd1cmVfUzIucG5nIiwgcGxvdCA9IEZpZ3VyZV9wdWJsaWNhdGlvbiwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMgQXBwZW5kaXggey50YWJzZXR9CgojIyBTZXNzaW9uIEluZm8gCmBgYHtyLCBlY2hvID0gRkFMU0V9CnNlc3Npb25JbmZvKCkKYGBgCgojIEV4cHJlc3Npb24gcGxvdHMKCiMjIyMgRXhwcmVzc2lvbiAtIHJhdyAtIFZpcmlkaXMKYGBge3IsIGZpZy5oZWlnaHQgPSAxNSwgZmlnLndpZHRoID0gMTV9CiMjIGZpbmQgYSBnb29kIHJpbmcgbWFya2VyLCB0byBzZWUgaWYgdGhlcmUgaXMgYSBiZXR0ZXIgb25lIHRoYW4gdGhlIG9uZXMgcmVwb3J0ZWQKI21hcmtlcnNfcmluZyA8LSBGaW5kTWFya2Vycyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBpZGVudC4xID0gYygiNCIsICI1IiwgIjE2IiwgIjExIiwgIjciLCAiMyIsICI5IiwgIjAiLCAiMjIiKSkKI2hlYWQobWFya2Vyc19yaW5nKQoKIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMTQzNzUwMCAtIEFQMkcgLSBjb21taXRtZW50CiMgUEJBTktBLTA4MzEwMDAgLSBNU1AxIC0gbGF0ZSBhc2V4dWFsCiMgUEJBTktBLTExMDIyMDAgLSBNU1A4IC0gZWFybHkgYXNleHVhbCAoZnJvbSBCb3pkZWNoIHBhcGVyKQojIFBCQU5LQS0wNzExOTAwIC0gSFNQNzAgLSBwcm9tb3RlciB1c2VkIGZvciBHRlAgYW5kIFJGUCBleHByZXNzaW9uIGluIHRoZSBtdXRhbnRzCiMgUEJBTktBLTE0MDA0MDAgLSBGQU1CIC0gcmluZyBtYXJrZXIgLSBkaXNjb3ZlcmVkIGJ5IGxvb2tpbmcgZm9yIG1hcmtlciBnZW5lcyBpbiBkYXRhCiMgUEJBTktBLTA3MjI2MDAgLSBGYW0tYjIgLSByaW5nIG1hcmtlciAtIGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzUxMTMwMzEvIAoKCm1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMxOTUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoY2NwMiksICIoRmVtYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxNjEwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1nMSksICIoTWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9BUDJHIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhhcDJnKSwgIihDb21taXRtZW50KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA4MzEwMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1zcDEpLCAiKFNjaGl6b250KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01TUDggPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1zcDgpLCAiKEFzZXh1YWwpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfU0JQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMTMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoc2JwMSksICIoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9GQU1CIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzIyNjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhmYW0tYjIpLCAgIihSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X0hTUDcwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzExOTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKEhTUDcwKSwgICIoUmVwb3J0ZXIpIiwiXG4iLCAiUEJBTktBXzA3MTE5MDAiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIHBsb3QKIyMgY293cGxvdCBtZXRob2QKbWFya2VyX2dlbmVfcGxvdF9hbGwgPC0gcGxvdF9ncmlkKG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwgbWFya2VyX2dlbmVfcGxvdF9NU1A4LCBtYXJrZXJfZ2VuZV9wbG90X01TUDEsIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLCBtYXJrZXJfZ2VuZV9wbG90X01HMSwgbWFya2VyX2dlbmVfcGxvdF9IU1A3MCwgbnJvdz0zKQoKbWFya2VyX2dlbmVfcGxvdF9hbGwKCiMjIHBhdGNod29yayBtZXRob2QKI21hcmtlcl9nZW5lX3Bsb3RfRkFNQiArIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCArIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSArIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRyArIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiArIG1hcmtlcl9nZW5lX3Bsb3RfTUcxICsgbWFya2VyX2dlbmVfcGxvdF9IU1A3MApgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIHJhdyAtIHB1cnBsZQpgYGB7ciwgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSAxNX0KCm1hcmtlcl9nZW5lX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDNEM0QzIiwgIiMxRDE1NjQiKSkoNTApCgptYXJrZXJfZ2VuZV9wbG90X0NDUDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIkNDUDIgKEZlbWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfTUcxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDE2MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiTUcxIChNYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9BUDJHIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJBUDJHIChDb21taXRtZW50KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9NU1AxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wODMxMDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJNU1AxIChTY2hpem9udCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQOCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMjIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiTVNQOCAoQXNleHVhbCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfU0JQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMTMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiU0JQMSAoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiRmFtLWIyIChSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9IU1A3MCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcxMTkwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCIoSFNQNzA7IFJlcG9ydGVyKSIsIlxuIiwgIlBCQU5LQV8wNzExOTAwIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgojIyBwbG90CiMjIGNvd3Bsb3QgbWV0aG9kCm1hcmtlcl9nZW5lX3Bsb3RfYWxsIDwtIHBsb3RfZ3JpZChtYXJrZXJfZ2VuZV9wbG90X0ZBTUIsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCwgbWFya2VyX2dlbmVfcGxvdF9NU1AxLCBtYXJrZXJfZ2VuZV9wbG90X0FQMkcsIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiwgbWFya2VyX2dlbmVfcGxvdF9NRzEsIG1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAsIG5yb3c9MykKCm1hcmtlcl9nZW5lX3Bsb3RfYWxsCmBgYAoKIyMjIyBFeHByZXNzaW9uIC0gZGF0YSAtIHB1cnBsZQoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90XzE3IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTgxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzE5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTY1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzEwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTM0MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wODI4MDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X29vbSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzAyNzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzI5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlIDwtIHdyYXBfcGxvdHMobWFya2VyX2dlbmVfcGxvdF8xNyAsIG1hcmtlcl9nZW5lX3Bsb3RfMiAsIG1hcmtlcl9nZW5lX3Bsb3RfMTkgLCBtYXJrZXJfZ2VuZV9wbG90XzIwICwgbWFya2VyX2dlbmVfcGxvdF8xMyAsIG1hcmtlcl9nZW5lX3Bsb3RfMTAgLCBtYXJrZXJfZ2VuZV9wbG90XzMgLCBtYXJrZXJfZ2VuZV9wbG90X29vbSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjkgLCBtYXJrZXJfZ2VuZV9wbG90XzIxICwgbmNvbCA9IDQpCiAgICAgICAgICAgCiMjIHByaW50Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZQpgYGAKCiMgRGVuc2l0eSBQbG90cwoKIyMjIyBEZW5zaXR5IC0gcHVycGxlCgpgYGB7cn0KIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMTQzNzUwMCAtIEFQMkcgLSBjb21taXRtZW50CiMgUEJBTktBLTA4MzEwMDAgLSBNU1AxIC0gbGF0ZSBhc2V4dWFsCiMgUEJBTktBLTExMDIyMDAgLSBNU1A4IC0gZWFybHkgYXNleHVhbCAoZnJvbSBCb3pkZWNoIHBhcGVyKQojIFBCQU5LQS0wNzExOTAwIC0gSFNQNzAgLSBwcm9tb3RlciB1c2VkIGZvciBHRlAgYW5kIFJGUCBleHByZXNzaW9uIGluIHRoZSBtdXRhbnRzCiMgUEJBTktBLTE0MDA0MDAgLSBGQU1CIC0gcmluZyBtYXJrZXIgLSBkaXNjb3ZlcmVkIGJ5IGxvb2tpbmcgZm9yIG1hcmtlciBnZW5lcyBpbiBkYXRhCiMgUEJBTktBLTA3MjI2MDAgLSBGYW0tYjIgLSByaW5nIG1hcmtlciAtIGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzUxMTMwMzEvIAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gImtzIikKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzNdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzZdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzldXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCmBgYAoKCiMjIyMgRGVuc2l0eSAtdmlyaWRpcwoKYGBge3J9CiMgUEJBTktBLTEzMTk1MDAgLSBDQ1AyIC0gZmVtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wNDE2MTAwIC0gTUcxIC0gZHluZW5pbiBoZWF2eSBjaGFpbiAtIG1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKIyBQQkFOS0EtMDcxMTkwMCAtIEhTUDcwIC0gcHJvbW90ZXIgdXNlZCBmb3IgR0ZQIGFuZCBSRlAgZXhwcmVzc2lvbiBpbiB0aGUgbXV0YW50cwojIFBCQU5LQS0xNDAwNDAwIC0gRkFNQiAtIHJpbmcgbWFya2VyIC0gZGlzY292ZXJlZCBieSBsb29raW5nIGZvciBtYXJrZXIgZ2VuZXMgaW4gZGF0YQojIFBCQU5LQS0wNzIyNjAwIC0gRmFtLWIyIC0gcmluZyBtYXJrZXIgLSBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1MTEzMDMxLyAKCm1hcmtlcnNfbGlzdCA8LSBjKCJQQkFOS0EtMDgyODAwMCIsICJQQkFOS0EtMTMwMjcwMCIsICJQQkFOS0EtMTQ0NzkwMCIsICJQQkFOS0EtMDEwMjQwMCIsICJQQkFOS0EtMDcxNjUwMCIsICJQQkFOS0EtMDQxMzQwMCIsICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgpsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzIDwtIHBsb3RfZGVuc2l0eSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBtYXJrZXJzX2xpc3QsIGpvaW50ID0gRkFMU0UsIGNvbWJpbmUgPSBGQUxTRSwgZGltcyA9IGMoMSwyKSwgcGFsID0gInBsYXNtYSIsIG1ldGhvZCA9ICJrcyIpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSApKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbN11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMTBdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCmBgYAoKIyMjIyBEZW5zaXR5IC0gdmlyaWRpcwpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBQQkFOS0EtMDgyODAwMCAgICAgICAgIEdDU0tPLTMgIEdEMQoKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQzIAojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMTQxODEwMCAgICAgICAgR0NTS08tMTcgIEZEMyAgIAojIFBCQU5LQS0xNDM1MjAwICAgICAgICBHQ1NLTy0yMCAgRkQ0IAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gImtzIikKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1szXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpICkrIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKCiMjIElGIHB1dHRpbmcgaW4gTUFJTiAtIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTkpKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSA0LjAsIHRpdGxlID0gIiIpKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCgojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDUKCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCgptYXJrZXJzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTE0NTQ4MDAiLCAiUEJBTktBLTA5MDIzMDAiLCAiUEJBTktBLTE0MTgxMDAiLCAiUEJBTktBLTE0MzUyMDAiKQoKbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lcyA8LSBwbG90X2RlbnNpdHkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbWFya2Vyc19saXN0LCBqb2ludCA9IEZBTFNFLCBjb21iaW5lID0gRkFMU0UsIGRpbXMgPSBjKDEsMiksIHBhbCA9ICJwbGFzbWEiLCBtZXRob2QgPSAid2tkZSIsIHNsb3QgPSAnZGF0YScpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgojIyBvbGQgY29sb3VyIHNjYWxlOiBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCApCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKYGBgCgoKCgoK